def remove_background(image): """ Removes background from image """ # Paramters. BLUR = 21 CANNY_THRESH_1 = 10 CANNY_THRESH_2 = 30 MASK_DILATE_ITER = 10 MASK_ERODE_ITER = 10 MASK_COLOR = (0.0, 0.0, 1.0) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Edge detection. edges = cv2.Canny(gray, CANNY_THRESH_1, CANNY_THRESH_2) edges = cv2.dilate(edges, None) edges = cv2.erode(edges, None) # Find contours in edges, sort by area contour_info = [] contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) for c in contours: contour_info.append(( c, cv2.isContourConvex(c), cv2.contourArea(c), )) contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True) max_contour = contour_info[0] # Create empty mask. mask = np.zeros(edges.shape) cv2.fillConvexPoly(mask, max_contour[0], (255)) # Smooth mask and blur it. mask = cv2.dilate(mask, None, iterations=MASK_DILATE_ITER) mask = cv2.erode(mask, None, iterations=MASK_ERODE_ITER) mask = cv2.GaussianBlur(mask, (BLUR, BLUR), 0) mask_stack = np.dstack([mask] * 3) # Blend masked img into MASK_COLOR background mask_stack = mask_stack.astype('float32') / 255.0 image = image.astype('float32') / 255.0 masked = (mask_stack * image) + ((1 - mask_stack) * MASK_COLOR) masked = (masked * 255).astype('uint8') c_red, c_green, c_blue = cv2.split(image) img_a = cv2.merge((c_red, c_green, c_blue, mask.astype('float32') / 255.0)) return img_a * 255
def convex(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) img1 = img.copy() imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thr = cv2.threshold(imgray, defThr, 255, 0) cv2.imshow('thr', thr) impDef.close_window() contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] ## 코드영역 따기 cntI = 0 for i in contours: cnt0 = contours[cntI] area = cv2.contourArea(cnt0) print('면적 : ', area) #영역의 크기가 45000 보다 크고 50000보다 작은경우만 출력 if area >= 45000 and area < 50000: cv2.drawContours(img1, [cnt0], 0, (0, 0, 255), 2) cv2.imshow('contour', img1) impDef.close_window() cntI = cntI + 1 ## cv2.drawContours(img, [cnt], 0, (0, 255, 0), 3) check = cv2.isContourConvex(cnt) # cv2.isContourConvex() 함수는 인자로 입력된 Contour가 Convex Hull 인지 체크합니다. # 만만 Convex Hull이라면 True를 리턴하고 그렇지 않으면 False를 리턴합니다. if not check: hull = cv2.convexHull(cnt) cv2.drawContours(img1, [hull], 0, (0, 255, 0), 3) cv2.imshow('convexhull', img1) # check 값이 False인 경우, 다시 말하면 우리가 주목하는 Contour가 Convex Hull이 # 아니라면 cv2.convexHull() 함수를 이용해 원본이미지의 contours[1]에 대한 # convex hull 곡선을 구합니다. cv2.imshow('contour', img) impDef.close_window()
def reconstruct(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) # 中心点 M = cv2.moments(contour_reconstruct) # 计算第一条轮廓的各阶矩,字典形式 center_x = int(M["m10"] / M["m00"]) center_y = int(M["m01"] / M["m00"]) black_np = np.ones(img.shape, np.uint8) # 创建黑色幕布 black = cv2.drawContours(black_np, contour_reconstruct, -1, (255, 255, 255), 3) # 绘制白色轮廓 black = cv2.circle(black, (center_x, center_y), 4, 255, -1) # 绘制中心点 cv2.circle(img, (center_x, center_y), 5, 255, -1) # 绘制中心点 point = [] # 二维数组转坐标形式 for idx in range(len(contour_reconstruct)): str1 = str( contour_reconstruct[idx]).lstrip('[[').rstrip(']]').split( " ") # [[010 200]]去头尾,按空格分割['','10','200'] while '' in str1: str1.remove('') # 去空格 point.append((int(str1[0]), int(str1[1]))) if point[idx]: cv2.circle(black, point[idx], 3, (0, 255, 255), thickness=-1, lineType=cv2.FILLED) cv2.putText(black, "{}".format(idx), point[idx], cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2, lineType=cv2.LINE_AA) # print(contour_reconstruct) print(point) # 凸包 hull = cv2.convexHull(contour_reconstruct) # 寻找凸包,得到凸包的角点 print("部分凸包信息:") print(hull[0]) # [[194 299]](坐标) hull2 = cv2.convexHull(contour_reconstruct, returnPoints=False) print(hull2[0]) # [20](cnt中的索引) print(contour_reconstruct[31]) # [[146 33]] print(cv2.isContourConvex(hull)) # True是否为凸型 dist = cv2.pointPolygonTest(contour_reconstruct, (center_x, center_y), True) # 中心点的最小距离 print(dist) cv2.polylines(img, [hull], True, (255, 255, 255), 3) # 绘制凸包 plt.figure(figsize=(10, 10)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.xlabel(u'凸包轮廓图', fontsize=20) plt.subplot(1, 2, 2) plt.imshow(cv2.cvtColor(black, cv2.COLOR_BGR2RGB)) plt.xlabel(u'傅里叶描述子和重心', fontsize=20) plt.show() #cv2.imshow("contour_reconstruct", img) # cv2.imwrite('recover.png',img) return img
def detect_coordinates2(image_address): cv.namedWindow('Trackbar', cv.WINDOW_NORMAL) cv.createTrackbar('lh', 'Trackbar', 36, 255, nothing) cv.createTrackbar('ls', 'Trackbar', 0, 255, nothing) cv.createTrackbar('lv', 'Trackbar', 0, 255, nothing) cv.createTrackbar('uh', 'Trackbar', 86, 86, nothing) cv.createTrackbar('us', 'Trackbar', 255, 255, nothing) cv.createTrackbar('uv', 'Trackbar', 255, 255, nothing) cv.createTrackbar('min_rad', 'Trackbar', 5, 50, nothing) cv.createTrackbar('max_rad', 'Trackbar', 10, 50, nothing) #cv.createTrackbar('lh_s', 'Trackbar', 0, 255, nothing) #cv.createTrackbar('ls_s', 'Trackbar', 0, 255, nothing) #cv.createTrackbar('lv_s', 'Trackbar', 0, 255, nothing) #cv.createTrackbar('uh_s', 'Trackbar', 0, 255, nothing) #cv.createTrackbar('us_s', 'Trackbar', 0, 255, nothing) #cv.createTrackbar('uv_s', 'Trackbar', 0, 255, nothing) circle_coordinates = [] cue_ball_coordinate = [] cue_stick_coordinate = [] while (True): circle_coordinates.clear() cue_ball_coordinate.clear() frame = cv.imread(image_address, 1) frame_copy = frame.copy() frame_copy = cv.medianBlur(frame_copy, 3) hsv = cv.cvtColor(frame_copy, cv.COLOR_BGR2HSV) hsv_cue = hsv.copy() lh = cv.getTrackbarPos('lh', 'Trackbar') ls = cv.getTrackbarPos('ls', 'Trackbar') lv = cv.getTrackbarPos('lv', 'Trackbar') uh = cv.getTrackbarPos('uh', 'Trackbar') us = cv.getTrackbarPos('us', 'Trackbar') uv = cv.getTrackbarPos('uv', 'Trackbar') #lh_s = cv.getTrackbarPos('lh_s', 'Trackbar') #ls_s = cv.getTrackbarPos('ls_s', 'Trackbar') #lv_s = cv.getTrackbarPos('lv_s', 'Trackbar') #uh_s = cv.getTrackbarPos('uh_s', 'Trackbar') #us_s = cv.getTrackbarPos('us_s', 'Trackbar') #uv_s = cv.getTrackbarPos('uv_s', 'Trackbar') min_rad = cv.getTrackbarPos('min_rad', 'Trackbar') max_rad = cv.getTrackbarPos('max_rad', 'Trackbar') lower_green = np.array([lh, ls, lv]) upper_green = np.array([uh, us, uv]) lower_white = np.array([0, 0, 168]) upper_white = np.array([172, 111, 255]) lower_pink = np.array([125, 100, 186]) upper_pink = np.array([166, 123, 219]) mask_white = cv.inRange(hsv_cue, lower_white, upper_white) mask = cv.inRange(hsv, lower_green, upper_green) mask = cv.bitwise_not(mask, mask=None) mask_stick = cv.inRange(hsv, lower_pink, upper_pink) contours, _ = cv.findContours(mask, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) contours_white_ball, _ = cv.findContours(mask_white, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) contours_stick, _ = cv.findContours(mask_stick, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) for contour in contours_stick: #approx_stick = cv.approxPolyDP( #contour,0.01*cv.arcLength(contour,True),True) M_stick = cv.moments(contour) if M_stick['m00'] == 0: continue cX_stick = M_stick['m10'] / M_stick['m00'] cY_stick = M_stick['m01'] / M_stick['m00'] cv.circle(frame, (int(cX_stick), int(cY_stick)), 1, (123, 55, 55), 2) cue_stick_coordinate = [cX_stick, cY_stick] for contour in contours_white_ball: approx_white = cv.approxPolyDP(contour, 0.01 * cv.arcLength(contour, True), True) x_white = approx_white.ravel()[0] y_white = approx_white.ravel()[1] M = cv.moments(contour) if M['m00'] == 0: continue cX_white = M['m10'] / M['m00'] cY_white = M['m01'] / M['m00'] #if len(approx_white) == 4: # _, _, w, h = cv.boundingRect(approx_white) # aspectRatio = float(w)/h # if aspectRatio >= 0.95 and aspectRatio <= 1.05: # cv.circle(frame, (int(cX_white), int(cY_white)), 1, (255, 0, 255), 2) if len(approx_white) > 10: k = cv.isContourConvex(approx_white) if k == 0: continue radius_white = math.sqrt((cX_white - x_white)**2 + (cY_white - y_white)**2) if radius_white < min_rad or radius_white > max_rad: continue cv.circle(frame, (int(cX_white), int(cY_white)), int(radius_white) * 2, (100, 100, 100), 2) cv.circle(frame, (int(cX_white), int(cY_white)), 1, (255, 100, 100), 2) cue_ball_coordinate = [cX_white, cY_white, radius_white] for contour in contours: if len(cue_ball_coordinate) != 0: cX_white = cue_ball_coordinate[0] cY_white = cue_ball_coordinate[1] approx = cv.approxPolyDP(contour, 0.01 * cv.arcLength(contour, True), True) x = approx.ravel()[0] y = approx.ravel()[1] M = cv.moments(contour) if M['m00'] == 0: continue cX = M['m10'] / M['m00'] cY = M['m01'] / M['m00'] if len(approx) > 10: if len(cue_ball_coordinate) != 0: distance = math.sqrt((cX - cX_white)**2 + (cY - cY_white)**2) if distance < min_rad: continue radius = math.sqrt((cX - x)**2 + (cY - y)**2) if radius < min_rad or radius > max_rad: continue cv.circle(frame, (int(cX), int(cY)), 1, (0, 255, 0), 2) cv.circle(frame, (int(cX), int(cY)), 2 * int(radius), (0, 255, 255), 2) circle_coordinates.append([cX, cY, radius]) cv.imshow('Image', frame) cv.imshow('Imag2', mask) if cv.waitKey(1) & 0xFF == 27: break cv.destroyAllWindows() return circle_coordinates, cue_ball_coordinate, cue_stick_coordinate
# Contour Approximation approximates a contour shape to another shape with less number of vertices depending upon the precision we specify. epsilon = 0.05 * cv2.arcLength(cnt, True) # The second argument is called epsilon, which is maximum distance from contour to approximated contour. It is an accuracy parameter. approx = cv2.approxPolyDP(cnt, epsilon, True) approx2 = cv2.approxPolyDP(cnt, 0.1 * epsilon, True) # Convex Hull will look similar to contour approximation, but it is not (Both may provide same results in some cases). Here, cv2.convexHull() function checks a curve for convexity defects and corrects it. Generally speaking, convex curves are the curves which are always bulged out, or at-least flat. And if it is bulged inside, it is called convexity defects. # points are the contours we pass into. # hull is the output, normally we avoid it. # clockwise : Orientation flag. If it is True, the output convex hull is oriented clockwise. Otherwise, it is oriented counter-clockwise. # returnPoints : By default, True. Then it returns the coordinates of the hull points. If False, it returns the indices of contour points corresponding to the hull points. hull = cv2.convexHull(cnt) # Check if a curve is convex or not. k = cv2.isContourConvex(cnt) print(k) draw_approx = cv2.drawContours(img_rgb, [approx], 0, (0, 255, 0), 5) draw_approx2 = cv2.drawContours(img_rgb2, [approx2], 0, (100, 190, 255), 5) draw_approx3 = cv2.drawContours(img_rgb3, [hull], 0, (0, 255, 255), 5) # image must be rgb or you'll get black contours which cannot be easily recognized. plt.subplot(2, 2, 1), plt.imshow(img, cmap='gray') plt.title('Original'), plt.xticks([]), plt.yticks([]) plt.subplot(2, 2, 2), plt.imshow(draw_approx, cmap='gray') plt.title('epsilon = 5% of the arc length'), plt.xticks([]), plt.yticks([]) plt.subplot(2, 2, 3), plt.imshow(draw_approx2, cmap='gray') plt.title('epsilon = 0.5% of the arc length'), plt.xticks([]), plt.yticks([])
sys.exit() img = cv.resize(img, (0, 0), fx=0.3, fy=0.3) img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) _, img_binary = cv.threshold(img_gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU) contours, _ = cv.findContours(img_binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE) dw, dh = 900, 500 import pytesseract for pts in contours: if cv.contourArea(pts) > 5000: approx = cv.approxPolyDP(pts, cv.arcLength(pts, True) * 0.02, True) if len(approx) == 4 and cv.isContourConvex(approx): cv.polylines(img, pts, True, (0, 0, 255)) srcQuad = reorderPts(approx.reshape(4, 2)) dstQuad = np.array([[0, dh], [dw, dh], [dw, 0], [0, 0]], dtype=np.float32) pers = cv.getPerspectiveTransform(srcQuad, dstQuad) img_dst = cv.warpPerspective(img, pers, (dw, dh), flags=cv.INTER_CUBIC) dst_rgb = cv.cvtColor(img_dst, cv.COLOR_BGR2RGB) print( pytesseract.image_to_string( dst_rgb, lang='Hangul+Hangul_vert+eng+eng_vert'))
# hull = cv2.convexHull(points[, hull[, clockwise[, returnPoints]] # Arguments details: # points are the contours we pass into. # hull is the output, normally we avoid it. # clockwise : Orientation flag. If it is True, the output convex hull is oriented clockwise. Otherwise, it is oriented counter-clockwise. # returnPoints : By default, True. Then it returns the coordinates of the hull points. If False, it returns the indices of contour points corresponding to the hull points. # So to get a convex hull as in above image, following is sufficient: hull = cv2.convexHull(cnt) hullcon = cv2.drawContours(img.copy(), [hull], -1, (0,0,255), 3) cv2.imshow('hull', hullcon) # Checking Convexity # There is a function to check if a curve is convex or not, cv2.isContourConvex(). It just return whether True or False. Not a big deal. print cv2.isContourConvex(cnt) # Bounding Rectangle # There are two types of bounding rectangles. # a. Straight Bounding Rectangle # It is a straight rectangle, it doesn’t consider the rotation of the object. So area of the bounding rectangle won’t be minimum. It is found by the function cv2.boundingRect(). # Let (x,y) be the top-left coordinate of the rectangle and (w,h) be its width and height. x,y,w,h = cv2.boundingRect(cnt) print cv2.boundingRect(cnt) straightRect = cv2.rectangle(img.copy(),(x,y),(x+w,y+h),(0,255,0),2) cv2.imshow('straightRect', straightRect)