在下圖中,我使用 opencv harris 角檢測器僅檢測正方形的角(以及外部正方形內的較小正方形)。但是,我也檢測到影像側面的數字的角落。我怎樣才能讓它只關注正方形而不是數字?代碼、輸入影像和輸出影像如下:
import cv2 as cv
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv.cornerHarris(gray, 2, 3, 0.04)
dst = cv.dilate(dst,None)
# Threshold for an optimal value, it may vary depending on the image.
img[dst>0.01*dst.max()]=[0,0,255]
cv.imshow('dst', img)
輸入影像

Harris角點檢測器的輸出

uj5u.com熱心網友回復:
這是使用傳統影像處理的一種潛在方法:
獲取二值影像。我們

檢測到的水平線
->水平遮罩

檢測到的垂直線
->垂直蒙版

按位和兩個掩碼
->檢測到的交叉點->角->清理角

The results aren't perfect but it's pretty close. The problem comes from the noise on the vertical mask due to the slanted image. If the image was centered without an angle, the results would be ideal. You can probably fine tune the kernel sizes or iterations to get better results.
Code
import cv2 import numpy as np # Load image, create horizontal/vertical masks, Gaussian blur, Adaptive threshold image = cv2.imread('1.png') original = image.copy() horizontal_mask = np.zeros(image.shape, dtype=np.uint8) vertical_mask = np.zeros(image.shape, dtype=np.uint8) gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (3,3), 0) thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 23, 7) # Remove small noise on thresholded image cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: area = cv2.contourArea(c) if area < 150: cv2.drawContours(thresh, [c], -1, 0, -1) # Detect horizontal lines dilate_horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10,1)) dilate_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, dilate_horizontal_kernel, iterations=1) horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,1)) detected_lines = cv2.morphologyEx(dilate_horizontal, cv2.MORPH_OPEN, horizontal_kernel, iterations=1) cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(image, [c], -1, (36,255,12), 2) cv2.drawContours(horizontal_mask, [c], -1, (255,255,255), 2) # Remove extra horizontal lines using contour area filtering horizontal_mask = cv2.cvtColor(horizontal_mask,cv2.COLOR_BGR2GRAY) cnts = cv2.findContours(horizontal_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: area = cv2.contourArea(c) if area > 1000 or area < 100: cv2.drawContours(horizontal_mask, [c], -1, 0, -1) # Detect vertical dilate_vertical_kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (1,7)) dilate_vertical = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, dilate_vertical_kernel, iterations=1) vertical_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (1,2)) detected_lines = cv2.morphologyEx(dilate_vertical, cv2.MORPH_OPEN, vertical_kernel, iterations=4) cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(image, [c], -1, (36,255,12), 2) cv2.drawContours(vertical_mask, [c], -1, (255,255,255), 2) # Find intersection points vertical_mask = cv2.cvtColor(vertical_mask,cv2.COLOR_BGR2GRAY) combined = cv2.bitwise_and(horizontal_mask, vertical_mask) kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2,2)) combined = cv2.morphologyEx(combined, cv2.MORPH_OPEN, kernel, iterations=1) # Highlight corners cnts = cv2.findContours(combined, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: # Find centroid and draw center point try: M = cv2.moments(c) cx = int(M['m10']/M['m00']) cy = int(M['m01']/M['m00']) cv2.circle(original, (cx, cy), 3, (36,255,12), -1) except ZeroDivisionError: pass cv2.imshow('thresh', thresh) cv2.imshow('horizontal_mask', horizontal_mask) cv2.imshow('vertical_mask', vertical_mask) cv2.imshow('combined', combined) cv2.imshow('original', original) cv2.imshow('image', image) cv2.waitKey()
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/450084.html
