def opencv_fitEllipse(img, method="Direct"): #assert binary_mask.min() >= 0.0 and binary_mask.max() <= 1.0 # points = np.argwhere(binary_mask == 1) # TODO: tune threshold contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # c_img = cv2.drawContours(img, contours, -1, (0, 255, 0), 1) # plt.figure() # plt.imshow(c_img) # plt.show() for c in contours: ellipse = cv2.fitEllipse(c) if method == "AMS": for c in contours: ellipse = cv2.fitEllipseAMS(c) elif method == "Direct": for c in contours: ellipse = cv2.fitEllipseDirect(c) elif method == "Simple": for c in contours: ellipse = cv2.fitEllipse(c) else: raise ValueError("Wrong method") return ellipse
def ellipse_heuristic(c, shape): # get_convex_hull(laplacian_smoothing(c, n=16)) c = get_convex_hull(c) ellipse = cv2.fitEllipseAMS(np.reshape(c, (-1, 2))) e_mask = np.zeros(shape, np.uint8) c_mask = np.zeros(shape, np.uint8) center_mask = np.zeros(shape, np.uint8) e_mask = cv2.ellipse(e_mask, ellipse, 255, -1) c_mask = cv2.drawContours(c_mask, [c], -1, 255, -1) center_mask = cv2.rectangle(center_mask, (0, 100), (shape[1], shape[0] - 100), 255, -1) _, (x, y), _ = ellipse if y < x: x, y = y, x # print x / float(y) if x / float(y) < 0.1: return 0 intersection = e_mask & c_mask & center_mask union = (e_mask | c_mask) & center_mask us = float(np.sum(union)) if us == 0: return 0 h = np.sum(intersection) / us return h
def ellipse_fit(points, method="Direct"): if method == "AMS": (xx, yy), (MA, ma), angle = cv2.fitEllipseAMS(points) elif method == "Direct": (xx, yy), (MA, ma), angle = cv2.fitEllipseDirect(points) elif method == "Simple": (xx, yy), (MA, ma), angle = cv2.fitEllipse(points) return (xx, yy), (MA, ma), angle
def detect1( self, c ): # I feel like we should get the center in subtract (or right after) and the shape here if len(c): epsilon = 0.1 * cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, epsilon, True) cv2.drawContours(self.out, [approx], 0, Color.MAGENTA, 1) if len(c) >= 5: ellipse_mask = np.zeros((self.h, self.w), dtype=np.uint8) rectangle_mask = ellipse_mask.copy() #for mask rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.int0(box) cv2.drawContours(rectangle_mask, [box], 0, 255, -1) ellipse = cv2.fitEllipseAMS(c) #make a fit function iterator cv2.ellipse(ellipse_mask, ellipse, 255, -1) rect_err_px = cv2.bitwise_xor(self.mask, rectangle_mask) circ_err_px = cv2.bitwise_xor(self.mask, ellipse_mask) rect_err = cv2.countNonZero(rect_err_px) circ_err = cv2.countNonZero(circ_err_px) cv2.putText(self.out, "eR: %2.f" % rect_err, (400, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, Color.GREEN, 2) cv2.putText(self.out, "eC: %2.f" % circ_err, (400, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.5, Color.YELLOW, 2) if rect_err < circ_err: #rectangle cv2.drawContours(self.out, [box], 0, Color.GREEN, 2) self.results[0] = 0 #state="TRACING" return False else: #circle self.results[0] = 1 cv2.ellipse(self.out, ellipse, Color.YELLOW, 2) #state="TRACKING" return False else: self.results[0] = -1 return True # (x,y),radius = cv2.minEnclosingCircle(c) # cv2.circle(ellipse_mask,(int(x),int(y)),int(radius),(0,255,255),2) #deficidnt logic will be here #after selection else: self.results[0] = -1 return True
def refine_ellipse(self, segments, idx): if len(idx) == 0: return None X, Y = [], [] for i in idx: X += segments[i][:, 0].tolist() Y += segments[i][:, 1].tolist() seg = numpy.vstack((X, Y), ).T ellipse = cv2.fitEllipseAMS(seg.astype(numpy.float32)) return ellipse
def estimate_ellipse(self, segments, s1, s2): seg = numpy.vstack((segments[s1], segments[s2])) ellipse = cv2.fitEllipseAMS(seg) if not self.is_good_ellipse(ellipse): return None, [] ellipse_mask = self.get_ellipse_mask(ellipse) is_match = numpy.array([ self.match_segment_ellipse(segment, ellipse_mask) for segment in segments ]) idx_match = numpy.where(is_match)[0] return ellipse, idx_match
def test_EllipseAMS(img): imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(src=imgray, thresh=180, maxval=255, type=cv2.THRESH_BINARY) find = np.where(binary == 255) # return tuple cnt = np.vstack(find).T cnt = cnt[:, np.newaxis, :][:, :, ::-1] # (6000, 1, 2) # 并不是把所有点都包裹进去 ellipse = cv2.fitEllipseAMS(cnt) # cvt binary to 3-channels for i in range(img.shape[0]): for j in range(img.shape[1]): img[i][j] = [binary[i][j], binary[i][j], binary[i][j]] cv2.ellipse(img, ellipse, color=(0, 255, 0), thickness=2) cv2.imshow('fitEllipseAMS', img)
def estimate_ellipse(self, segments, s1, s2=None): if s2 is not None: seg = numpy.vstack((segments[s1], segments[s2])) else: seg = segments[s1] ellipse = cv2.fitEllipseAMS(seg) if not self.is_good_ellipse(ellipse): return None, [] ellipse_mask = self.get_ellipse_mask(ellipse) #match1 = self.match_segment_ellipse(segments[s1], ellipse_mask) #match2 = self.match_segment_ellipse(segments[s2], ellipse_mask) #if not (match1 and match2): return None,[] is_match = numpy.array([ self.match_segment_ellipse(segment, ellipse_mask) for segment in segments ]) idx_match = numpy.where(is_match)[0] return ellipse, idx_match
def bboxes(path): name = 'Boxer' cv2.namedWindow(name) # cv2.resizeWindow(name, 800,600) cv2.moveWindow(name, 100, 960) #blr=cv2.blur(img, (5,5)) cv2.createTrackbar('blur', name, 0, 5, nothing) cv2.createTrackbar('sig_space', name, 0, 120, nothing) cv2.createTrackbar('sig_color', name, 0, 120, nothing) cv2.createTrackbar('canny', name, 0, 100, nothing) #flags fancy = 0 org = 0 draw = 0 can = 1 #vars b = 1 ss = 20 sc = 20 t = 50 #index idx = 0 images = os.listdir(path) bg = cv2.imread('bg.jpg') for filename in images: print("Loading ", filename) img = cv2.imread(path + '/' + filename) #cv2.imshow(name, img) cv2.imshow("Subtracted", cv2.subtract(bg, img)) while (1): if fancy: blr = cv2.bilateralFilter(img, b, ss, sc) else: blr = cv2.blur(img, (b, b)) if can: binary = cv2.Canny(blr, t, 3 * t) else: gray = cv2.cvtColor(blr, cv2.COLOR_BGR2GRAY) (t, binary) = cv2.threshold(gray, t, 255, cv2.THRESH_BINARY_INV) m2, contours, hierarchy = cv2.findContours(binary, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) N = len(contours) # number of conoturs if org: out = img.copy() else: out = cv2.cvtColor(binary, cv2.COLOR_GRAY2BGR) if draw and N: # safety c = contours[idx % N] # better safe then sorry #approx here cv2.drawContours(out, contours, -1, (0, 255, 0), 4) cv2.drawContours(out, [c], 0, (0, 0, 255), 4) (x, y, w, h) = cv2.boundingRect(c) cv2.rectangle(out, (x, y), (x + w, y + h), (255, 200, 100), 2, 1) if len(c) >= 5: ellipse = cv2.fitEllipseAMS( c) #make a fit function iterator cv2.ellipse(out, ellipse, (0, 255, 255), 2) # Rotated box # rect = cv.minAreaRect(cnt) # box = cv.boxPoints(rect) # box = np.int0(box) # cv.drawContours(img,[box],0,(0,0,255),2) cv2.putText(out, str(len(contours)), (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2) cv2.imshow(name, out) k = cv2.waitKey(30) & 0xFF if k == ord('x'): exit() elif k == ord('b'): fancy ^= 1 print("fancy blur: " + str(fancy)) elif k == ord('v'): org ^= 1 print("showing original img:" + str(org)) elif k == ord('c'): draw ^= 1 print("drawing contours: " + str(draw)) elif k == ord('m'): can ^= 1 print("canny vs threshold: " + str(can)) elif k == ord('a'): idx = (idx + 1) % len(contours) print("Drawing ROI #" + str(idx)) #next image elif k == ord('.'): print("Next image") break b = 2 * cv2.getTrackbarPos('blur', name) + 1 ss = cv2.getTrackbarPos('sig_space', name) sc = cv2.getTrackbarPos('sig_color', name) t = cv2.getTrackbarPos('canny', name) #def main(): cv2.destroyAllWindows()
mask[labels == label] = 255 # detect contours in the mask and grab the largest one cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) c = max(cnts, key=cv2.contourArea) # draw a circle enclosing the object #((x, y), r) = cv2.minEnclosingCircle(c) #cv2.circle(image, (int(x), int(y)), int(r), (0, 255, 0), 2) #cv2.putText(image, "#{}".format(label), (int(x) - 10, int(y)), # cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) # ellipse attempt (x, y), (MA, ma), angle = cv2.fitEllipseAMS(c) cv2.ellipse(image, (int(round(x)), int(round(y))), (int(round(MA / 2)), int(round(ma / 2))), int(round(angle)), 0, 360, (0, 255, 0), 2) #cv2.putText(image, "#{}".format(label), (int(x) - 10, int(y)), # cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) # cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]]) → Non # cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]]) → None # show the output image #cv2.imshow("Output", image) #cv2.waitKey(0) # save image status = cv2.imwrite('testresult.png', image)
def fit(TextoutFile, TextColorFile, PathClean): TextoutFileEx = os.path.basename(TextoutFile) TextFile = os.path.splitext(TextoutFileEx)[0] TextColorFileEx = os.path.basename(TextColorFile) TextCFile = os.path.splitext(TextColorFileEx)[0] print("------------------------- Fit & Crop -------------------------") print(TextFile) img = cv2.imread(TextoutFile) img2 = cv2.imread(TextColorFile) rows, cols = img.shape[:2] gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, threshold = cv2.threshold(gray, 20, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV) contours, hierarchy = cv2.findContours(threshold, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) print("contours :", len(contours)) minpass = rows * cols check = 0 stand = 0 OldAngle = 0 for cnt in contours: area = cv2.contourArea(cnt) if 200 < area < 0.4 * rows * cols: if area < minpass: print("--------------------------") print("ALL :", 0.4 * rows * cols) print("Letter :", area) rect = cv2.minAreaRect(cnt) #print(rect) box = cv2.boxPoints(rect) box = np.int0(box) ## cv2.drawContours(threshold,[box],0,(0,0,255),2) ## cv2.imshow("threshold",threshold) ellipse = cv2.fitEllipse(cnt) (x, y), (MA, ma), OldAngle = cv2.fitEllipseAMS(cnt) # get width and height of the detected rectangle width = int(rect[1][0]) height = int(rect[1][1]) src_pts = box.astype("float32") # corrdinate of the points in box points after the rectangle has been straightened dst_pts = np.array([[0, height - 1], [0, 0], [width - 1, 0], [width - 1, height - 1]], dtype="float32") # the perspective transformation matrix M = cv2.getPerspectiveTransform(src_pts, dst_pts) # directly warp the rotated rectangle to get the straightened rectangle warped = cv2.warpPerspective(img, M, (width, height)) warped2 = cv2.warpPerspective(img2, M, (width, height)) # put warped in bigger black picture h, w = warped.shape[:2] if h > w: size = h + 50 else: size = w + 50 Black = np.zeros((size, size, 3), np.uint8) Grey = np.zeros((size, size, 3), np.uint8) Grey[:] = (100, 100, 100) try: Black[int(size / 2 - h / 2):int(size / 2 + h / 2), int(size / 2 - w / 2):int(size / 2 + w / 2)] = warped # kernel_sharpening = np.array([[-1,-1,-1],[-1, 9,-1],[-1,-1,-1]]) # Black = cv2.filter2D(Black, -1, kernel_sharpening) Grey[int(size / 2 - h / 2):int(size / 2 + h / 2), int(size / 2 - w / 2):int(size / 2 + w / 2)] = warped2 cv2.imwrite("%s/%sclean.jpg" % (PathClean, TextFile), Black) print("%s/%sclean.jpg" % (PathClean, TextFile)) TextClean = ("%s/%sclean.jpg" % (PathClean, TextFile)) cv2.imwrite("%s/%scolor.jpg" % (PathClean, TextFile), Grey) print("%s/%scolor.jpg" % (PathClean, TextFile)) Textcolor = ("%s/%scolor.jpg" % (PathClean, TextFile)) except Exception: print( "------------ Error! Error! Error! Error! Error! ------------" ) continue check += 1 minpass = area stand += 1 if stand > check: print("ALL :", 0.6 * rows * cols) print("***No Text Found!!!!***") print("Letter :", area) check = stand size = 400 Black = np.zeros((size, size, 3), np.uint8) Grey = np.zeros((size, size, 3), np.uint8) Grey[:] = (100, 100, 100) cv2.imwrite("%s/%s[Not]clean.jpg" % (PathClean, TextFile), Black) print("Not Found :%s/%sOverclean.jpg" % (PathClean, TextFile)) TextClean = ("%s/%s[Not]clean.jpg" % (PathClean, TextFile)) cv2.imwrite("%s/%s[Not]color.jpg" % (PathClean, TextFile), Grey) print("%s/%sOvercolor.jpg" % (PathClean, TextFile)) Textcolor = ("%s/%s[Not]color.jpg" % (PathClean, TextFile)) return TextClean, Textcolor, OldAngle
def detect_ellipse(img): """ This function computes an image with a pixel set at the largest "wye" detected in the image The function returns the binary wye detection image, the threshold image, the smoothed contour, and the skeleton images as a tuple """ # apply a slight blur to help thresholding img = cv2.medianBlur(img, 5) h, w = np.shape(img) # apply adaptive thresholding to find lines thresh = 255 - cv2.adaptiveThreshold( img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 63, 15) # mask out some areas we wish to ignore (eg robot and horizon) thresh = cv2.ellipse(thresh, (w / 2, h), (400, 100), 0, 0, 360, (0, 0, 0), -1) thresh = cv2.rectangle(thresh, (0, 0), (w, 60), (0, 0, 0), -1) # thresh = cv2.rectangle(thresh, (0, 3*h/4), (w/4, h), (0,0,0), -1) # thresh = cv2.rectangle(thresh, (3*w/4, 3*h/4), (w, h), (0,0,0), -1) detect = np.zeros(thresh.shape, np.uint8) closed = np.zeros(thresh.shape, np.uint8) contours, heirarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contours = filter(lambda c: len(c) > 50, contours) # contours = map(lambda c: get_convex_hull(c), contours) contours = filter(lambda c: cv2.contourArea(get_convex_hull(c)) > 10000, contours) contours = filter(lambda c: ellipse_heuristic(c, img.shape) > 0.7, contours) ellipse = None if len(contours) > 0: # for c in contours: # print cv2.contourArea(get_convex_hull(c)), ellipse_heuristic(c, img.shape) # largest = max(contours, key = lambda c: ellipseScore(c)) largest = max( contours, key=lambda c: math.sqrt(cv2.contourArea(get_convex_hull(c)) ) * ellipse_heuristic(c, img.shape)) # largest = max(contours, key = lambda c: cv2.contourArea(c)) # largest = contours[] largest = laplacian_smoothing(largest, n=16) largest = get_convex_hull(largest) ellipse = cv2.fitEllipseAMS(np.reshape(largest, (-1, 2))) detect = cv2.ellipse(detect, ellipse, (255, 255, 255), -1) closed = cv2.drawContours(closed, [largest], -1, (255, 255, 255), -1) return ellipse, detect, thresh, closed
totImg = img.copy() for i in range(len(contours)): # 外接圆 - 红色 imgCp = img.copy() (x, y), radius = cv2.minEnclosingCircle(contours[i]) (x, y, radius) = np.int0((x, y, radius)) # 圆心和半径取整 cv2.circle(imgCp, (x, y), radius, (0, 0, 255), 2) # 拟合椭圆,方法返回的是一个RotatedRectangle,拟合的椭圆即为其内切椭圆 # 青色 ellipse = cv2.fitEllipse(contours[i]) cv2.ellipse(imgCp, ellipse, (255, 255, 0), 2) # 拟合椭圆的另外两种方法 # 蓝色 ellipse = cv2.fitEllipseAMS(contours[i]) cv2.ellipse(imgCp, ellipse, (255, 0, 0), 2) # 绿色 ellipse = cv2.fitEllipseDirect(contours[i]) cv2.ellipse(imgCp, ellipse, (0, 255, 0), 2) totImg = cv2.hconcat((totImg, imgCp)) cv2.imshow('Bounding Circle', totImg) # 考察轮廓的外接多边形 totImg = img.copy() for i in range(len(contours)): # 多边形逼近,得到多边形的角点。使用Douglas-Peucker算法 imgCp = img.copy() # epsilon表示近似多边形周长和源轮廓周长之间的差值,越小则多边形与源轮廓越相似
def process_sample(self): #--------------------------------------------Processamento da imagem-------------------------------------------- #-Normalização da imagem para o intervalo 0 a 255- img = cv2.normalize(self.img, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX) #-Redimensionamento da imagem para 256x256 pelo método de interpolação de área- img = cv2.resize(img, (256, 256), interpolation=cv2.INTER_AREA) #-Remoção de ruído da imagem- blur_img = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) blur_img = cv2.GaussianBlur(blur_img, (7, 7), 0) #-Divisão dos canais da imagem- _, _, b = cv2.split(blur_img) #-Segmentação da imagem através de limiarização do canal B (método de Otsu)- th, mask = cv2.threshold(b, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) cv2.imwrite('maskb.jpeg', mask) #-Gera um kernel elipsóide 3x3- kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) #-Aplica 5 iterações da operação morfológica de fechamento na máscara, utilizando o kernel criado- mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=5) #-Obtem os contornos da máscara- _, cnt, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #-Encontra o maior contorno em relação à sua área- max_cnt = max(cnt, key=cv2.contourArea) #-Define os parâmetros do menor retângulo que englobe o maior contorno encontrado- x, y, w, h = cv2.boundingRect(max_cnt) #-Combinação das imagens com a máscara para obtenção da Região de Interesse (ROI)- #-Imagem original (BGR)- img = cv2.bitwise_and(img, img, mask=mask) #-Recorta as imagens utilizando os parâmetros do retângulo obtido anteriormente- #-Recorte da imagem original- img = img[y:y + h, x:x + w] self.img_masked = img #-Recorta também a máscara utilizando os mesmos parâmetros- mask_rsz = mask[y:y + h, x:x + w] #-Redimensionamento das imagens para 256x256 pelo método de interpolação cúbica- #-Redimensionamento da imagem original- img = cv2.resize(img, (256, 256), interpolation=cv2.INTER_CUBIC) #-Redimensionamento da imagem L*a*b*- LAB_img = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) #-Redimensionamento da máscara- mask_rsz = cv2.resize(mask_rsz, (256, 256), interpolation=cv2.INTER_NEAREST) #----------------------------------------Fim do processamento da imagem----------------------------------------- #------------------------------------------Extração de características------------------------------------------ b, g, r = cv2.split(img) LAB_L, LAB_a, LAB_b = cv2.split(LAB_img) mask_rsz = cv2.bitwise_not(mask_rsz) #-------------DESCRITOR DE COR------------ LAB_a_ma = np.ma.masked_array(LAB_a, mask=mask_rsz) LAB_b_ma = np.ma.masked_array(LAB_b, mask=mask_rsz) LAB_a_hist = np.histogram(LAB_a_ma.compressed().ravel(), bins=np.arange(0, 256), density=True) LAB_b_hist = np.histogram(LAB_b_ma.compressed().ravel(), bins=np.arange(0, 256), density=True) #-----------DESCRITOR DE TEXTURA---------- #-Extrair o descritor de textura (Local Binary Patterns) dos canais da imagem RGB- LBP_b = feature.local_binary_pattern(b, LBP_pontos, LBP_raio, 'uniform') LBP_g = feature.local_binary_pattern(g, LBP_pontos, LBP_raio, 'uniform') LBP_r = feature.local_binary_pattern(r, LBP_pontos, LBP_raio, 'uniform') LBP_b_ma = np.ma.masked_array(LBP_b, mask=mask_rsz) LBP_g_ma = np.ma.masked_array(LBP_g, mask=mask_rsz) LBP_r_ma = np.ma.masked_array(LBP_r, mask=mask_rsz) #-Gerar o histograma do LBP dos canais RGB- LBP_hist_b = np.histogram(LBP_b_ma.compressed().ravel(), bins=np.arange(0, LBP_b_ma.max() + 1), density=True) LBP_hist_g = np.histogram(LBP_g_ma.compressed().ravel(), bins=np.arange(0, LBP_b_ma.max() + 1), density=True) LBP_hist_r = np.histogram(LBP_r_ma.compressed().ravel(), bins=np.arange(0, LBP_b_ma.max() + 1), density=True) #-----------DESCRITOR DE TAMANHO---------- #-Obtém o elipsoide que melhor se encaixa ao contorno- try: elipse = cv2.fitEllipseAMS(max_cnt) except cv2.error as e: print("ERRO ao obter elipse") else: #Extrai os valores dos eixos da elipse _, self.other_features, _ = elipse #----------VETOR DE CARACTERÍSTICAS--------- #-Expande o vetor de características com o histograma dos canais 'a' e 'b' da imagem L*a*b- self.feature_vector.extend(LAB_a_hist[0].flatten()) self.feature_vector.extend(LAB_b_hist[0].flatten()) #-Expande o vetor de características com o histograma da imagem LBP- self.feature_vector.extend(LBP_hist_b[0].flatten()) self.feature_vector.extend(LBP_hist_g[0].flatten()) self.feature_vector.extend(LBP_hist_r[0].flatten())