#!/usr/bin/env python # -*- encoding: utf-8 -*- ''' @File : roi_img_process.py @Contact : zpyovo@hotmail.com @License : (C)Copyright 2018-2019, Lab501-TransferLearning-SCUT @Description : @Modify Time @Author @Version @Desciption ------------ ------- -------- ----------- 2024/1/7 22:57 Pengyu Zhang 1.0 None ''' from __future__ import absolute_import from __future__ import division from __future__ import print_function import cv2 import numpy as np from matplotlib import pyplot as plt def preprocess_image(image,size,blur): # 将图像调整为固定大小 # image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if size !=-1: image = cv2.resize(image, (size, size), interpolation=cv2.INTER_AREA) if size == -1: image = cv2.cvtColor(np.array(image), cv2.COLOR_BGR2GRAY) if blur: kernel_size = 3 image = cv2.GaussianBlur(image, (kernel_size, kernel_size), sigmaX=1, sigmaY=0) return image def clos_open(input,B_p): _, binary_image = cv2.threshold(input, B_p, 255, cv2.THRESH_BINARY) # 定义结构元素(内核) kernel = np.ones((3, 3), np.uint8) # 开运算 opening = cv2.morphologyEx(binary_image, cv2.MORPH_OPEN, kernel) # 定义结构元素(内核) kernel = np.ones((3, 3), np.uint8) # 闭运算 closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel) return closing def img_angle(input): # canny边缘检测 eroded_canny = cv2.Canny(input, 50, 255, apertureSize=3) contours, hierarchy = cv2.findContours(eroded_canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 寻找最大元素 k = 0 index = 0 if len(contours) != 0: for i in range(len(contours)): j = contours[i].size if j > k: k = j index = i # 拟合旋转矩形 cnt = contours[index] rect = cv2.minAreaRect(cnt) angle = rect[2] box = cv2.boxPoints(rect) box = np.int0(box) # 对点按照y坐标排序(最上和最下的点) box = box[box[:, 1].argsort()] # 上边的两个点按照x坐标排序(决定左上和右上) top_two = box[:2] top_two = top_two[top_two[:, 0].argsort()] # 下边的两个点按照x坐标排序(决定左下和右下) bottom_two = box[2:] bottom_two = bottom_two[bottom_two[:, 0].argsort()] # 重新组合为左上、右上、右下、左下的顺序 ordered_box = np.array([top_two[0], top_two[1], bottom_two[1], bottom_two[0]]) return angle,ordered_box def angel_affine(input,angle): height, width = np.array(input).shape center = (width // 2, height // 2) if angle is not None and angle != 0.0: if angle > 45.0: angle = angle - 90 # rotate page if not straight relative to QR code M = cv2.getRotationMatrix2D(center, angle, 1.0) output = cv2.warpAffine(np.array(input), M, (width, height), flags=cv2.INTER_CUBIC,borderMode=cv2.BORDER_REPLICATE) return output def merge_overlapping_rectangles(rectangles): if len(rectangles) <= 1: return rectangles merged_rectangles = [] for rect in sorted(rectangles, key=lambda x: x[2]*x[3], reverse=True): x, y, w, h = rect if not any((x < x2 + w2 and x + w > x2 and y < y2 + h2 and y + h > y2) for x2, y2, w2, h2 in merged_rectangles): merged_rectangles.append(rect) return merged_rectangles def roi2_detector(input,min_area_threshold): # 使用 Canny 边缘检测 edges = cv2.Canny(input, 50, 255, apertureSize=3) # 寻找轮廓 contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 临时存储矩形 temp_rectangles = [] # 识别矩形轮廓 for contour in contours: # 轮廓近似 epsilon = 0.001 * cv2.arcLength(contour, True) approx = cv2.approxPolyDP(contour, epsilon, True) if len(approx) >= 4: x, y, w, h = cv2.boundingRect(approx) aspect_ratio = w / float(h) area_contour = cv2.contourArea(contour) if aspect_ratio >= 0.75 and aspect_ratio < 1.2 and min_area_threshold < area_contour < 15000: area_bounding_rect = w * h area_ratio = area_contour / area_bounding_rect if 0.75 < area_ratio < 1.05: temp_rectangles.append((x, y, w, h)) # 合并重叠的方框 merged_rectangles = merge_overlapping_rectangles(temp_rectangles) # 选择并绘制最大的方框 if merged_rectangles: outermost_rectangle = max(merged_rectangles, key=lambda x: x[2]*x[3]) rectangle_count = 1 return outermost_rectangle else: return None from PIL import Image def roi_img_processing(input): input_ray = cv2.cvtColor(np.array(input), cv2.COLOR_BGR2GRAY) img_resize = preprocess_image(input_ray, 128, blur=False) img_closing = clos_open(img_resize,B_p=50) # 闭运算 min_area_threshold=6500 roi_coordinate = roi2_detector(img_closing,min_area_threshold) if roi_coordinate is None: img_closing = clos_open(img_resize, B_p=100) # 闭运算 roi_coordinate = roi2_detector(img_closing,min_area_threshold) if roi_coordinate is None: return None x, y, w, h = roi_coordinate # 截取图像 input_fix = img_resize[y+1:y-1 + h, x+1:x-1 + w] output = preprocess_image(input_fix, 32, blur=True) return output def roi_detect(input): size = 128 height, width, _ = input.shape if height < size: img_resize = cv2.resize(np.array(input), (size, size), interpolation=cv2.INTER_AREA) else: img_resize = cv2.resize(np.array(input), (size, size), interpolation=cv2.INTER_LINEAR) image_gay = cv2.cvtColor(img_resize, cv2.COLOR_BGR2GRAY) min_area_threshold = 1000 img_closing = clos_open(image_gay, B_p=50) # 闭运算 roi_coordinate = roi2_detector(img_closing,min_area_threshold) if roi_coordinate is None : img_closing = clos_open(img_resize, B_p=100) # 闭运算 roi_coordinate = roi2_detector(img_closing,min_area_threshold) # print('150') if roi_coordinate is None : img_closing = clos_open(img_resize, B_p=150) # 闭运算 roi_coordinate = roi2_detector(img_closing,min_area_threshold) # print('100') if roi_coordinate is None : img_closing = clos_open(img_resize, B_p=120) # 闭运算 roi_coordinate = roi2_detector(img_closing,min_area_threshold) if roi_coordinate is None: img_closing = clos_open(img_resize, B_p=75) # 闭运算 roi_coordinate = roi2_detector(img_closing,min_area_threshold) if roi_coordinate is None: return None x, y, w, h = roi_coordinate # 截取图像 input_fix = img_resize[y + 1:y - 1 + h, x + 1:x - 1 + w] input_fix = Image.fromarray(np.uint8(input_fix)) return input_fix def roi_minAreaRect(input): img_closing = clos_open(input) # 闭运算 _, box = img_angle(img_closing) # 图像偏差角度 return box