def convex1(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thr = cv2.threshold(imgray, defThr, 255, 0) contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 원본 이미지의 6번째 contour인 contours[5]가 단풍잎 모양의 외곽을 에워싸고 있는 contour cnt = contours[5] # contour에 외접하는 똑바로 세워진 사각형을 얻기 위해 cv2.boundingRect() 함수를 이용합니다. x, y, w, h = cv2.boundingRect(cnt) #cv2.boudingRect()함수는 인자로 받은 contour에 외접하고 똑바로 세워진 직사각형의 # 좌상단 꼭지점 좌표 (x, y)와 가로 세로 폭을 리턴합니다. # 이렇게 얻은 좌표를 이용해 원본 이미지에 빨간색으로 사각형을 그립니다. cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 3) rect = cv2.minAreaRect(cnt) #cv2.minAreaRect() 함수는 인자로 입력한 contour에 외접하면서 면적이 가장 작은 직사각형을 구하는데 활용됩니다. # 이 함수의 리턴값은 좌상단 꼭지점 좌표 (x, y), 가로 세로 폭과 이 사각형이 기울어진 각도입니다. box = cv2.boxPoints(rect) #v2.boxPoints() 함수는 cv2.minAreaRect() 함수로 얻은 직사각형의 꼭지점 4개의 좌표를 얻기 위해 사용됩니다. box = np.int0(box) #좌표는 float형으로 리턴되므로 np.int0()로 정수형 값으로 전환한 후, 원본 이미지에 초록색 사각형을 그리는 겁니다. cv2.drawContours(img, [box], 0, (0, 255, 2), 3) cv2.imshow('retangle', img) impDef.close_window()
def draw_box(binary_image, init_image): # 產生等高線 _, contours, hierarchy = cv2.findContours(binary_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 建立除錯用影像 img_debug = init_image.copy() # 線條寬度 line_width = int(init_image.shape[1] / 255) # 以藍色線條畫出所有的等高線 # cv2.drawContours(img_debug, contours, -1, (255, 0, 0), line_width) # 找出面積最大的等高線區域 c = max(contours, key=cv2.contourArea) # 找出可以包住面積最大等高線區域的方框,並以綠色線條畫出來 x, y, w, h = cv2.boundingRect(c) outs = cv2.rectangle(img_debug, (x, y), (x + w, y + h), (0, 255, 0), line_width) cv2.imwrite('../images/Segmet_Images/box_Green.png', outs) # 嘗試在各種角度,以最小的方框包住面積最大的等高線區域,以紅色線條標示 rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.int0(box) Fin_image = cv2.drawContours(img_debug, [box], 0, (0, 0, 255), line_width) cv2.imwrite('../images/Segmet_Images/box_Rad.png', Fin_image)
def get_top_view(image, corners, make_square=True): # get bounding box rect = cv2.minAreaRect(corners) box = cv2.boxPoints(rect) box = np.int0(box) # cv2.drawContours(image, [box], 0, (0, 0, 255), 2) # rect = (center, shape, angle) # dimensions height = int(rect[1][1]) width = int(rect[1][0]) final = np.float32([[0,0],[width,0],[0,height],[width,height]]) # perspective transformation matrix transformation_matrix = cv2.getPerspectiveTransform(corners, final) warped = cv2.warpPerspective(image, transformation_matrix, (width, height)) side = max(width, height) if side < 200: return None, None, None # make it a square try: warped = cv2.resize(warped, (side,side), interpolation=cv2.INTER_CUBIC) warped = cv2.resize(warped, (450,450), interpolation=cv2.INTER_CUBIC) except Exception as e: print(e) return warped, transformation_matrix, (height,width)
def get_painting_from_roi(self, cntrs, img): """ It takes the contours of a painting and returns the painting extracted from the given image :param cntrs: contours of the image :param img: image containing paintings :return: painting extracted from the image """ # find the biggest countour (c) by the area c = max(cntrs, key=cv2.contourArea) rc = cv2.minAreaRect(c) box = cv2.boxPoints(rc) for p in box: pt = (p[0], p[1]) # print(pt) # cv2.circle(frame, pt, 5, (200, 0, 0), 2) # approximate the contour (approx) with 10% tolerance epsilon = 0.1 * cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, epsilon, True) x, y, w, h = cv2.boundingRect(approx) # draw the biggest contour (c) in green # cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) extracted_painting = img[y:y + h, x:x + w] return extracted_painting
def tran_xywha_to_rbox(xywha): """包装opencv的cv.boxPoints函数 Args: xywha: ((xy),(wh),angle)形式tuple或list, xy为中心点 """ if len(xywha) != 3: xywha = (xywha[:2], xywha[2:4], xywha[4]) return cv.boxPoints(xywha) # 返回4*2数组
def getCorners(self, contours): corners = 0 for i in range(len(contours)): rect = cv2.minAreaRect(contours[i]) center = rect[0] box = cv2.boxPoints(rect) box = np.int0(box) cv2.drawContours(self.img, [box], 0, (255, 0, 0), 2) corners += 1 return corners
def do_rectangles(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY)[1] thresh = 255 - thresh cv2.imshow('thresh', thresh) cv2.waitKey() kernel = np.array( [[1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1]], np.uint8) kernel3 = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], np.uint8) #dilation = cv2.dilate(thresh, kernel, iterations=4) #erosion = cv2.erode(dilation, kernel, iterations=2) # erosion = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel3) dilation = cv2.morphologyEx(erosion, cv2.MORPH_OPEN, kernel3) cv2.imshow('erosion7', erosion) cv2.imshow('dilation7', dilation) dilation = cv2.morphologyEx(dilation, cv2.MORPH_CLOSE, kernel) cv2.imshow('dilation3', dilation) cv2.waitKey() #exit() cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) cnts = imutils.grab_contours(cnts) disp = img.copy() clr = [0, 0, 0] for i in range(len(cnts)): idx = i % 3 clr[idx] = np.random.randint(0, 256) #x, y, w, h = cv2.boundingRect(cnts[i]) cv2.drawContours(disp, cnts, i, tuple(clr), 2) #cv2.rectangle(disp, (x, y), (x + w, y + h), clr, 2) rect = cv2.minAreaRect(cnts[i]) box = cv2.boxPoints(rect) box = np.int0(box) #cv2.drawContours(disp, [box], 0, tuple(clr), 2) cv2.imshow('disp', disp) cv2.waitKey() for c in cnts: eps = 0.045 * cv2.arcLength(c, False) approx = cv2.approxPolyDP(c, eps, True) if len(approx) > 3: cv2.drawContours(img, [c], 0, (0, 255, 0), 2) cv2.imshow('img', img) cv2.waitKey()
def run_grouping(self): self.generate_comp_bubble() while len(self.ungrouped_labels) > 0: curr_label = list(self.ungrouped_labels)[0] curr_bucket = self.grouplabel(label=curr_label, bucket=[curr_label]) self.grouped_labels.append(curr_bucket) self.ungrouped_labels = self.ungrouped_labels.difference( set(curr_bucket)) self.grouped_bubblebbox = [] self.grouped_annot_bubble = np.zeros(self.labelmask.shape, dtype=np.uint8) self.grouped_annot_bubble = cv2.cvtColor(self.grouped_annot_bubble, cv2.COLOR_GRAY2BGR) self.grouped_annot = np.zeros(self.labelmask.shape, dtype=np.uint8) self.grouped_annot = cv2.cvtColor(self.grouped_annot, cv2.COLOR_GRAY2BGR) for each_group in self.grouped_labels: mask = np.zeros(self.labelmask.shape, dtype=np.uint8) for each_label in each_group: label_ct, label_bx = self.get_attr(each_label, mode='proximity') radii = max([ np.linalg.norm(epnt[::-1] - label_ct) for epnt in label_bx ]) mask += self.create_circular_mask(label_ct[::-1], radii) contours, hierarchy = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) self.grouped_bubblebbox.append(contours) mask = np.zeros(self.labelmask.shape, dtype=np.uint8) for each_label in each_group: mask += self.labelmask == each_label mask *= 255 self.grouped_annot_bubble += cv2.cvtColor(mask.copy(), cv2.COLOR_GRAY2BGR) self.grouped_annot += cv2.cvtColor(mask.copy(), cv2.COLOR_GRAY2BGR) cv2.drawContours(self.grouped_annot_bubble, contours, -1, (0, 0, 255), self.bubble_width) rotrect = cv2.minAreaRect(contours[0]) combbbox = cv2.boxPoints(rotrect) self.grouped_annot += cv2.polylines(self.grouped_annot, np.int32([combbbox]), True, (0, 0, 255), 2) return self.grouped_labels, self.grouped_bubblebbox, self.grouped_annot_bubble, self.grouped_annot, self.maskviz, self.maskcomb
def trans_polygon_to_rbox(polygon): """求polygon的最小外接旋转矩形 Args: polygon: 一维数组,或(K, 2)数组 """ if not isinstance(polygon, np.ndarray): polygon = np.array(polygon) polygon = polygon.reshape(-1, 2).astype(np.float32) segm_hull = cv.convexHull(polygon, clockwise=False) xywha = cv.minAreaRect(segm_hull) rbox = cv.boxPoints(xywha).reshape(-1).tolist() return rbox
def generate_geo_map(self, img, boxes, index_map, train_mask): geo_map = np.zeros((img.shape[0], img.shape[1], 5), dtype=np.float32) # geo_map for i, box in enumerate(boxes): poly = box.reshape(-1, 2) index_map = index_map * train_mask xy = np.argwhere(index_map == i + 1) if xy.size == 0: continue xy = xy[:, ::-1] #n*2 rotate_rect = cv2.minAreaRect(poly) box_w, box_h, angle = rotate_rect[1][0], rotate_rect[1][1], abs( rotate_rect[2]) rect = cv2.boxPoints(rotate_rect) # 4*2 # sort rect p_lowest = np.argmax(rect[:, 1]) #lowest index p_lowest_count = np.count_nonzero(rect[:, 1] == rect[p_lowest, 1]) if p_lowest_count == 2: p_0 = np.argmin(np.sum(rect, axis=1)) p_1 = (p_0 + 1) % 4 p_2 = (p_0 + 2) % 4 p_3 = (p_0 + 3) % 4 elif angle <= 45: p_3 = p_lowest p_0 = (p_lowest + 1) % 4 p_1 = (p_lowest + 2) % 4 p_2 = (p_lowest + 3) % 4 elif angle > 45: angle = angle - 90 p_2 = p_lowest p_3 = (p_lowest + 1) % 4 p_0 = (p_lowest + 2) % 4 p_1 = (p_lowest + 3) % 4 rect = rect[[p_0, p_1, p_2, p_3]] print(f"angle: {angle}") # calculate_distance for x, y in xy: geo_map[y, x, 0] = self.calculate_distance(x, y, rect[0], rect[1]) geo_map[y, x, 1] = self.calculate_distance(x, y, rect[1], rect[2]) geo_map[y, x, 2] = self.calculate_distance(x, y, rect[2], rect[3]) geo_map[y, x, 3] = self.calculate_distance(x, y, rect[3], rect[0]) geo_map[y, x, 4] = angle return geo_map
def process_image(self, debug_mode): result_plates = [] working_image = np.copy(self.input_image) if debug_mode: show(working_image, "input_image") working_image = cv2.cvtColor(working_image, cv2.COLOR_BGR2GRAY) if debug_mode: show(working_image, "after cvtColor") working_image = cv2.Sobel(working_image, -1, 1, 0) if debug_mode: show(working_image, "after sobel") _, working_image = cv2.threshold(working_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) if debug_mode: show(working_image, "after threshold") closing_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, self.morph_closing_shape) working_image = cv2.morphologyEx(working_image, cv2.MORPH_CLOSE, closing_kernel) if debug_mode: show(working_image, "after morph closing") opening_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, self.morph_opening_shape) working_image = cv2.morphologyEx(working_image, cv2.MORPH_OPEN, opening_kernel) if debug_mode: show(working_image, "after morph opening") _, contours, _ = cv2.findContours(working_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) tmp_img_for_contours = np.copy(self.input_image) cv2.drawContours(tmp_img_for_contours, contours, -1, (255, 0, 255), 2) if debug_mode: show(tmp_img_for_contours, "all contours") tmp_img_for_valid_contours = np.copy(self.input_image) for contour in contours: if self.is_valid_contour(contour): rect = cv2.minAreaRect(contour) box = cv2.boxPoints(rect) box = np.int0(box) # cast float to long result_plates.append(box) cv2.drawContours(tmp_img_for_valid_contours, [box], -1, (255, 0, 0), 1) cv2.drawContours(tmp_img_for_valid_contours, contour, -1, (255, 0, 255), 2) if debug_mode: show(tmp_img_for_valid_contours, "valid contours") return result_plates
def getPerspectiveSrc(c): result = [] rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.int0(box) for i in range(len(box)): for j in range(len(box)): distance = int(twoPointEuclideanDistance(box[i], box[j])) if distance not in result and distance > 0: result.append(distance) if len(result) == 3: return result pass return None
def handle_ann(self, ann): """如果想自定义ann处理方式,继承此类,然后重新实现此方法""" if self.num_coors == 4: bboxes = cvtools.x1y1wh_to_x1y1x2y2(ann['bbox']) elif self.num_coors == 8: segm = ann['segmentation'][0] if len(segm) != 8: segm_hull = cv.convexHull( np.array(segm).reshape(-1, 2).astype(np.float32), clockwise=False) xywha = cv.minAreaRect(segm_hull) segm = cv.boxPoints(xywha).reshape(-1).tolist() bboxes = segm else: raise RuntimeError('不支持的坐标数!') return bboxes + [1.]
def FindRed(img) : lower = np.array([0, 0, 200]) upper = np.array([60, 60, 255]) filtered = cv2.inRange(img, lower, upper) blurred = cv2.GaussianBlur(filtered, (5, 5), 0) cnts, _ = cv2.findContours(blurred.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) rtimg = np.zeros_like(img) point_list = [] for cnt in cnts: # compute the (rotated) bounding box around then # contour and then draw it rect = np.int32(cv2.boxPoints(cv2.minAreaRect(cnt))) rtimg = cv2.drawContours(img, [rect], -1, (0, 255, 0), 2) point = [rect[2][0] + (rect[0][0] - rect[1][0])/2, rect[2][1] + (rect[1][1]- rect[2][1])/2] point_list.append(point) return rtimg, point_list
def get_contours(origin, img): # window_title = "im" # 获取轮廓 # img = cv2.imread(image_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (3, 3), 0) edges = cv2.Canny(blur, 10, 200) # Edge detection edges = cv2.dilate(edges, None) # 默认(3x3) edges = cv2.erode(edges, None) # Find contours in edges(binary image) contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=cv2.contourArea, reverse=True) max_contour = contours[0] epsilon = 0.001 * cv2.arcLength(max_contour, True) approx = cv2.approxPolyDP(max_contour, epsilon, True) # print(approx) box = cv2.minAreaRect(approx) center, wh, angle = box angle = int(abs(angle)) wh = (int(wh[0]), int(wh[1])) center = (int(center[0]), int(center[1])) # print(center, wh, angle) # cv2.putText( # img, "{}".format(angle), center, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2, # ) box = cv2.boxPoints(box) # 坐标转换成大图坐标系 center = np.array(center) + np.array(origin) box = np.array(box) + np.array(origin) box = np.int0(box) # cv2.drawContours(img, [box], -1, 255, 2) # cv2.imshow(window_title, img) # cv2.waitKey(0) # cv2.destroyAllWindows() # return 中心点、角度、最大轮廓、宽高 return center, angle, box, wh
def drawRotatedRectangle(img, c): rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.int0(box) print(box.shape) cv2.drawContours(img, [box], 0, (0, 0, 255), 1) # for i in range(len(box)): # for j in range(len(box)): # result = twoPointEuclideanDistance(box[i],box[j]) # print("point {i} to point {j} = {result}".format(i=i,j=j,result=result)) # pass for i in range(len(box)): x, y = box[i, :] cv2.putText(img, str(i), (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) pass pass
def croping(paper, original, ime_firme): cells = [] ret, thresh_gray = cv2.threshold(paper, 200, 255, cv2.THRESH_BINARY) contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) for c in contours: rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.int0(box) x, y, w, h = cv2.boundingRect(c) crop = original[y:y + h, x:x + w] textract(crop) response = Jsonify() print(response) f = open('response.txt', 'w') f.write(response) f.close()
def remove_border(contour, ary): """Remove everything outside a border contour.""" # Use a rotated rectangle (should be a good approximation of a border). # If it's far from a right angle, it's probably two sides of a border and # we should use the bounding box instead. c_im = np.zeros(ary.shape) r = cv2.minAreaRect(contour) degs = r[2] if angle_from_right(degs) <= 10.0: box = cv2.boxPoints(r) box = np.int0(box) cv2.drawContours(c_im, [box], 0, 255, -1) cv2.drawContours(c_im, [box], 0, 0, 4) else: x1, y1, x2, y2 = cv2.boundingRect(contour) cv2.rectangle(c_im, (x1, y1), (x2, y2), 255, -1) cv2.rectangle(c_im, (x1, y1), (x2, y2), 0, 4) return np.minimum(c_im, ary)
def is_valid_contour(self, contour): rect = cv2.minAreaRect(contour) if 45 < abs(rect[2]) < 135: # rect is rotated ~90 degrees width = rect[1][1] height = rect[1][0] else: width = rect[1][0] height = rect[1][1] if self.plate_min_width < width < self.plate_max_width and self.plate_min_height < height < self.plate_max_height: aspect_ratio = float(width) / height if self.plate_aspect_ratio_range[ 0] < aspect_ratio < self.plate_aspect_ratio_range[1]: extend = cv2.contourArea(contour) / (rect[1][0] * rect[1][1]) if extend > self.min_plate_extend: box = cv2.boxPoints(rect) box = np.int0(box) box_copy = list(box) point = box_copy[0] del (box_copy[0]) distances_to_first_point = [ ((p[0] - point[0])**2 + (p[1] - point[1])**2) for p in box_copy ] sorted_dists = sorted(distances_to_first_point) opposite_point = box_copy[distances_to_first_point.index( sorted_dists[1])] if abs(point[0] - opposite_point[0]) > 0: contour_angle = abs( float(point[1] - opposite_point[1])) / abs(point[0] - opposite_point[0]) contour_angle = rad_to_deg(math.atan(contour_angle)) if contour_angle <= self.plate_max_angle: return True return False
def get_cropped_min_area_rect(contour, img): rect = cv2.minAreaRect(contour) width = rect[1][1] height = rect[1][0] # The lowest point of the rectangle will always be the first element. # All other points will follow in a clockwise-direction. # We make sure that the first element is always the top left corner. corners = cv2.boxPoints(rect) # We rotate until the closest point to the origin is at the front while np.argmin(corners.sum(axis=1)) != 0: corners = np.roll(corners, -1, axis=0) height, width = width, height dst = np.array( [[0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1]], dtype=np.float32) M = cv2.getPerspectiveTransform(corners, dst) return cv2.warpPerspective(img, M, (math.ceil(width), math.ceil(height)), flags=cv2.INTER_CUBIC)
def geContours(img,imgContour): contours, heirarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: area = cv2.contourArea(cnt) areaMin = 100 if area > areaMin: cv2.drawContours(imgContour, cnt, -1, (255, 0, 255), 5) peri = cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, 0.02 * peri, True) x , y , w, h = cv2.boundingRect(approx) cv2.rectangle(imgContour, (x , y ), (x + w , y + h ), (0, 255, 0), 5) M = cv2.moments(cnt) cx = int(M["m10"]/M["m00"]) cy = int(M["m01"]/M["m00"]) cv2.circle(imgContour, (cx, cy), 7, (255, 255, 255), -1) rotrect = cv2.minAreaRect(cnt) box = cv2.boxPoints(rotrect) box = np.int0(box) angle = rotrect[-1] if angle < -45: angle = -(90 + angle) else: angle = -angle print((round(angle)),"deg") print((cx, cy),"") cv2.putText(imgContour, "Area: " + str(int(area)), (x + w + 20, y + 35), cv2.FONT_HERSHEY_COMPLEX, 0.4, (0, 255, 0), 1) cv2.putText(imgContour, "Degree: " + str(int(angle)), (x + w + 20, y + 50), cv2.FONT_HERSHEY_COMPLEX, 0.4, (0, 255, 0), 1)
def draw_circle(self, img, descirptor_in_use): """获取外接轮廓 :param res: 输入图像,傅里叶描述子 :return: 重绘图像 """ contour_reconstruct = np.fft.ifft(descirptor_in_use) # 傅里叶反变换 contour_reconstruct = np.array( [contour_reconstruct.real, contour_reconstruct.imag]) contour_reconstruct = np.transpose(contour_reconstruct) # 转换矩阵 contour_reconstruct = np.expand_dims(contour_reconstruct, axis=1) # 改变数组维度在axis=1轴上加1 if contour_reconstruct.min() < 0: contour_reconstruct -= contour_reconstruct.min() contour_reconstruct *= img.shape[0] / contour_reconstruct.max() contour_reconstruct = contour_reconstruct.astype(np.int32, copy=False) x, y, w, h = cv2.boundingRect(contour_reconstruct) # 外接矩形 cv2.rectangle(img, (x, y), (x + w, y + h), (255, 225, 0), 3) rect = cv2.minAreaRect(contour_reconstruct) # 最小外接矩形 box = np.int0(cv2.boxPoints(rect)) # 矩形的四个角点取整 cv2.drawContours(img, [box], 0, (0, 255, 255), 3) (x, y), radius = cv2.minEnclosingCircle(contour_reconstruct) # 最小外接圆 (x, y, radius) = np.int0((x, y, radius)) # 圆心和半径取整 cv2.circle(img, (x, y), radius, (0, 255, 0), 2) ellipse = cv2.fitEllipse(contour_reconstruct) # 拟合椭圆 cv2.ellipse(img, ellipse, (0, 0, 255), 2) df = pd.DataFrame(np.random.rand(10, 4), columns=[u'外接矩形', u'最小外接矩阵', u'外接圆', u'椭圆']) fig = df.plot(figsize=(6, 6)) # 创建图表对象,并复制给fig plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.xlabel(u'图像轮廓', fontsize=20) plt.show() return img
def Identificar_objeto(c, crop_img_contour, img): #logica para processar os dados de cada contorno encontrado # id do objeto i = 0 tabela = [] for cnt in c: (x, y), _ = cv2.minEnclosingCircle( cnt) #função que ajuda a descobrir o centro do objeto center = (int(x), int(y)) cv2.putText(crop_img_contour, str(i), center, cv2.FONT_HERSHEY_SIMPLEX, 3, (255, 255, 255), 8, cv2.LINE_AA) #escreve o Id do objeto no centro box = [] rect = cv2.minAreaRect( cnt) #acha os pontos do retangulo q vai delimitar o objeto box_float = cv2.boxPoints(rect) box = np.int0(box_float) #conversão para manipulação #modo como o openCV numera os vértices ###3### #2###4# ###1## cv2.drawContours(crop_img_contour, [box], 0, (225, 0, 255), 2) #desenhar o retangulo #distancias entres os pontos pra saber qual o melhor lado pra pegar # distancia 0 garra anti horaria # distancia 1 garra horaria distancia_0 = math.sqrt((box[0][0] - box[1][0])**2 + (box[0][1] - box[1][1])**2) distancia_1 = math.sqrt((box[0][0] - box[3][0])**2 + (box[0][1] - box[3][1])**2) #delimitador de tamanho max de face limite = 300 if ((distancia_0 > limite) and (distancia_1 > limite)): cv2.putText(crop_img_contour, "IMPOSSIVEL", center, cv2.FONT_HERSHEY_SIMPLEX, 3, (0, 0, 255), 8, cv2.LINE_AA) else: #escolher a face de menor tamanho, pq uma delas pode ser fora do limite permitido (maior que a garra) #lógica para converter ângulo em ãngulo_braco (a logica muda de acordo com o sentido de giro)... o braço entende de -90 a 90 if (distancia_0 > distancia_1): angulo = Angulo(box[0], box[3], center, img) angulo_braco = math.fabs(angulo) - 90 angulo_braco = round(angulo_braco, 2) else: angulo = Angulo(box[0], box[1], center, img) angulo_braco = 90 - angulo angulo_braco = round(angulo_braco, 2) #para evitar angulos grandes e o braço girar mais do que deve. Essa logica inverte a face que o braço vai pegar if angulo_braco > 90: angulo_braco = angulo_braco - 180 if angulo_braco < -90: angulo_braco = angulo_braco + 180 #converter de pixls (x e y) para dados reais (braço) centro_conv_X, centro_conv_Y = Conversao_centro(center) #correção necessário, pois o ponto de giro não é fixo... lógica desenvolvida por mapeamento e obtenção de padrão de erro if angulo_braco < 0: centro_conv_X = centro_conv_X + (0.1625 * angulo_braco) centro_conv_X = round(centro_conv_X, 3) #organizar para alimentar o dataframe objeto = [] objeto.append(i) objeto.append(centro_conv_X) objeto.append(centro_conv_Y) objeto.append(angulo_braco) tabela.append(objeto) i += 1 return crop_img_contour, tabela
def draw_boxes_texts(img, boxes, texts=None, colors=None, line_width=1, draw_start=True, box_format='x1y1x2y2'): """Draw bboxes on an image. Args: img (str or ndarray): The image to be displayed. boxes (list or ndarray): A list of ndarray of shape (k, 4). texts (list): A list of shape (k). colors (list[tuple or Color]): A list of colors. line_width (int): Thickness of lines. draw_start (bool): Draw a dot at the first vertex of the box. box_format (str): x1y1x2y2(default), x1y1wh, xywh, xywha, polygen """ assert box_format in ('x1y1x2y2', 'x1y1wh', 'xywh', 'xywha', 'polygen'), 'not supported box format!' img = imread(img) if len(boxes) == 0: return img boxes = copy.deepcopy(boxes) # convert bbox type to int if not isinstance(boxes, np.ndarray): if box_format != 'polygen': boxes = np.array(boxes) if box_format != 'xywha': boxes = boxes.astype(np.int) if len(boxes.shape) == 1: boxes = [boxes] else: boxes = [list(map(int, box)) for box in boxes] else: boxes = boxes.astype(np.int) if texts is not None and not isinstance(texts, (list, np.ndarray)): texts = [texts] if isinstance(img, Image.Image): img = cv.cvtColor(np.asarray(img), cv.COLOR_RGB2BGR) if not isinstance(img, np.ndarray): return if colors == 'random': colors = np.random.randint(0, 255, size=(len(boxes), 3)) colors = [tuple(map(int, color)) for color in colors] text_color = (0, 255, 255) thickness = line_width font = cv.FONT_HERSHEY_SIMPLEX for idx, box in enumerate(boxes): # default color: red, BGR order box_color = (0, 0, 255) if colors is None else colors[idx] if box_format == 'x1y1x2y2': cv.rectangle(img, tuple(box[0:2]), tuple(box[2:4]), box_color, thickness) elif box_format == 'x1y1wh': box[0:4] = cvtools.x1y1wh_to_x1y1x2y2(list(box[0:4])) cv.rectangle(img, tuple(box[0:2]), tuple(box[2:4]), box_color, thickness) elif box_format == 'xywh': box[0:4] = cvtools.xywh_to_x1y1x2y2(list(box[0:4])) cv.rectangle(img, tuple(box[0:2]), tuple(box[2:4]), box_color, thickness) elif box_format == 'xywha': rrect = tuple(box[:2]), tuple(box[2:4]), box[4] box = cv.boxPoints(rrect).astype(np.int) # box = np.int0(box) cv.drawContours(img, [box], 0, box_color, thickness) box = box.reshape((-1, )) elif box_format == 'polygen': for i in np.arange(2, len(box), 2): cv.line(img, tuple(box[i - 2:i]), tuple(box[i:i + 2]), box_color, thickness) cv.line(img, tuple(box[-2:]), tuple(box[:2]), box_color, thickness) # cv.line(img, tuple(box[:2]), tuple(box[2:4]), box_color, thickness) # cv.line(img, tuple(box[2:4]), tuple(box[4:6]), box_color, thickness) # cv.line(img, tuple(box[4:6]), tuple(box[6:8]), box_color, thickness) # cv.line(img, tuple(box[6:]), tuple(box[:2]), box_color, thickness) if draw_start: cv.circle(img, tuple(box[:2]), radius=5, color=text_color, thickness=-1) if texts is not None: cv.putText(img, texts[idx], (box[0] + 2, box[1] - 2), font, 0.5, text_color, 1) return img
cv2.CHAIN_APPROX_SIMPLE) for i in range(len(contours)): cnt = contours[i] # Calculate contour area and screen out small areas area = cv2.contourArea(cnt) if (area < 1000): continue # Find the smallest rectangle rect = cv2.minAreaRect(cnt) #print("Rect: ", rect) # Box is the coordinate of four points box = cv2.boxPoints(rect) box = np.int0(box) # Computing height and width height = abs(box[0][1] - box[2][1]) width = abs(box[0][0] - box[2][0]) # According to the characteristics of the text, select those too thin rectangles, leaving flat ones. if (height > width * 1.3): continue region.append(box) # Segmentate into images i = 0 for box in region:
cnts = imutils.grab_contours(cnts) # Draw/print contour information print("\nContour Information:") for c in cnts: x, y, w, h = cv2.boundingRect(c) # get the bounding box area = w * h # calculate bounding box area center = (int(x + w / 2), int(y + h / 2)) # calculate center # skip contours with too small area if (w * h) < 1000: continue cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1) # draw green bounding box cv2.circle(image, center, 2, (255, 0, 0), 2) # draw blue centerpoint rect = cv2.minAreaRect(c) # get the min area rectangle box = cv2.boxPoints(rect) # extract box points for drawing cv2.drawContours(image, [np.int0(box)], 0, (0, 0, 255)) # draw red min area rectangle print( "\n\t-bounding box-\n\tx={}\ty={}\n\tw={}\th={}\n\tcenter={}\n\tarea={}" .format(x, y, w, h, center, area)) cv2.imshow("Mask", gray) # Display image mask cv2.imshow("Shapes", image) # Display image with shapes cv2.waitKey(0)
# sort the contours from left-to-right and initialize the # 'pixels per metric' calibration variable (cnts, _) = contours.sort_contours(cnts) pixelsPerMetric = None # loop over the contours individually for c in cnts: # if the contour is not sufficiently large, ignore it if cv2.contourArea(c) < 500: continue # compute the rotated bounding box of the contour orig = image.copy() box = cv2.minAreaRect(c) box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box) box = np.array(box, dtype="int") # order the points in the contour such that they appear # in top-left, top-right, bottom-right, and bottom-left # order, then draw the outline of the rotated bounding # box box = perspective.order_points(box) cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2) # loop over the original points and draw them for (x, y) in box: cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1) # unpack the ordered bounding box, then compute the midpoint # between the top-left and top-right coordinates, followed by
def read_grid(image): sudoku = "" side = image.shape[0] // 9 # this is a square image - side will be 50 offset = 0.1 * side # for borders for i in range(9): for j in range(9): # coordinates if corners of a small box top = max(int(round(side * i + offset)), 0) left = max(int(round(side * j + offset)), 0) right = min(int(round(side * (j + 1) - offset)), image.shape[0]) bottom = min(int(round(side * (i + 1) - offset)), image.shape[0]) # finding the contour inside the box crop = image[top:bottom, left:right] gray = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (7, 7), 0) thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # finding the largest valid contour max_area = 1 largest_contour = None for cnt in contours: area = cv2.contourArea(cnt) if area > side * side * 0.04 and area > max_area: max_area = area largest_contour = cnt # if there is no contour, then the box must be empty if largest_contour is None: sudoku += "0" continue # crop out the largest contour i.e. the digit rect = cv2.minAreaRect(largest_contour) box = cv2.boxPoints(rect) box = np.int0(box) minx = max(min(box, key=lambda g: g[0])[0] - 3, 0) miny = max(min(box, key=lambda g: g[1])[1] - 3, 0) maxx = min(max(box, key=lambda g: g[0])[0] + 3, int(side)) maxy = min(max(box, key=lambda g: g[1])[1] + 3, int(side)) # gray image of only the number number_image = gray[miny:maxy, minx:maxx] # OCR custom_config = r' --psm 6 -c tessedit_char_whitelist=123456789' text = pt.image_to_string(number_image, config=custom_config) # if i == 7 and j == 3: # cv2.imshow("cropped",number_image) # print(text) try: num = int(text) sudoku += str(num) except: # if there is a big contour but its not a digit, # this frame is invalid, ignore it return None return sudoku
# set up the ROI for tracking roi = frame[y:y+h, x:x+w] hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255.))) roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180]) cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX) # setup the termination criteria, either 10 iteration or move by atleast 1 pt term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1) cv2.imshow('roi', roi) while(1): ret, frame = cap.read() if ret == True: hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1) # apply meanshift to get the new location ret, track_window = cv2.CamShift(dst, track_window, term_crit) # Draw it on image pts = cv2.boxPoints(ret) pts = np.int0(pts) final_image = cv2.polylines(frame, [pts], True, (0, 255, 0), 3) cv2.imshow(' final_image', final_image) cv2.imshow('dst', dst) k = cv2.waitKey(30) & 0xFF if k == 27: break else: break
def img_dimension(img): image = img # Read image and preprocess # image = cv2.imread(img_path) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (9, 9), 0) edged = cv2.Canny(blur, 50, 100) edged = cv2.dilate(edged, None, iterations=1) edged = cv2.erode(edged, None, iterations=1) # show_images([blur, edged]) # Find contours cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) # Sort contours from left to right as leftmost contour is reference object (cnts, _) = contours.sort_contours(cnts) # Remove contours which are not large enough cnts = [x for x in cnts if cv2.contourArea(x) > 100] # cv2.drawContours(image, cnts, -1, (0,255,0), 3) # show_images([image, edged]) print(len(cnts)) # Reference object dimensions # Here for reference I have used a 2cm x 2cm square ref_object = cnts[0] box = cv2.minAreaRect(ref_object) box = cv2.boxPoints(box) box = np.array(box, dtype="int") box = perspective.order_points(box) (tl, tr, br, bl) = box dist_in_pixel = euclidean(tl, tr) dist_in_cm = 2 pixel_per_cm = dist_in_pixel / dist_in_cm # Draw remaining contours count = 0 for cnt in cnts: count = count + 1 if (count == 2): box = cv2.minAreaRect(cnt) box = cv2.boxPoints(box) box = np.array(box, dtype="int") box = perspective.order_points(box) (tl, tr, br, bl) = box cv2.drawContours(image, [box.astype("int")], -1, (0, 0, 255), 2) mid_pt_horizontal = (tl[0] + int(abs(tr[0] - tl[0]) / 2), tl[1] + int(abs(tr[1] - tl[1]) / 2)) mid_pt_verticle = (tr[0] + int(abs(tr[0] - br[0]) / 2), tr[1] + int(abs(tr[1] - br[1]) / 2)) wid = euclidean(tl, tr) / pixel_per_cm ht = euclidean(tr, br) / pixel_per_cm # if (count == 2): # e_text3.delete(1.0, "END") width = "{:.1f}cm".format(wid) e_text3.delete("1.0", "end") e_text3.insert("end-1c", width) height = "{:.1f}cm".format(ht) e_text4.delete("1.0", "end") e_text4.insert("end-1c", height) # e_text3.insert("hi") print("{:.1f}cm".format(wid), "{:.1f}cm".format(ht)) cv2.putText(image, "{:.1f}cm".format(wid), (int(mid_pt_horizontal[0] - 15), int(mid_pt_horizontal[1] - 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) cv2.putText( image, "{:.1f}cm".format(ht), (int(mid_pt_verticle[0] + 10), int(mid_pt_verticle[1])), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)