Sam*_*m O 4 python opencv image-processing computer-vision edge-detection
我试图找到墨渍角的准确位置,如下所示:
我的想法是将线条拟合到边缘,然后找到它们相交的位置。到目前为止,我已经尝试使用 cv2.approxPolyDP() 和各种 epsilon 值来近似边缘,但这看起来不像是要走的路。我的 cv.approxPolyDP 代码给出了以下结果:
理想情况下,这就是我想要制作的(画在油漆上):
是否有针对此类问题的 CV 功能?我已经考虑在阈值步骤之前使用高斯模糊,尽管该方法对于角点查找来说似乎不太准确。此外,我希望这对旋转图像具有鲁棒性,因此在没有其他考虑的情况下过滤垂直和水平线不一定有效。
代码*:
import numpy as np
from PIL import ImageGrab
import cv2
def process_image4(original_image): # Douglas-peucker approximation
# Convert to black and white threshold map
gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
(thresh, bw) = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# Convert bw image back to colored so that red, green and blue contour lines are visible, draw contours
modified_image = cv2.cvtColor(bw, cv2.COLOR_GRAY2BGR)
contours, hierarchy = cv2.findContours(bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(modified_image, contours, -1, (255, 0, 0), 3)
# Contour approximation
try: # Just to be sure it doesn't crash while testing!
for cnt in contours:
epsilon = 0.005 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# cv2.drawContours(modified_image, [approx], -1, (0, 0, 255), 3)
except:
pass
return modified_image
def screen_record():
while(True):
screen = np.array(ImageGrab.grab(bbox=(100, 240, 750, 600)))
image = process_image4(screen)
cv2.imshow('window', image)
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
screen_record()
Run Code Online (Sandbox Code Playgroud)
这是使用阈值+形态学操作的潜在解决方案:
形态学操作。我们执行一系列形态学的开闭来平滑图像并去除噪声
cv2.arcLength
和cv2.approxPolyDP
再画到这个面具cv2.goodFeaturesToTrack
进行角点检测。看看这个对每个参数的解释这是每个步骤的可视化:
二值图像->
形态学操作->
近似掩码->
检测到的角点
这里是角坐标:
(103, 550)
(1241, 536)
Run Code Online (Sandbox Code Playgroud)
这是其他图像的结果
(558, 949)
(558, 347)
Run Code Online (Sandbox Code Playgroud)
最后对于旋转的图像
(201, 99)
(619, 168)
Run Code Online (Sandbox Code Playgroud)
代码
import cv2
import numpy as np
# Load image, bilaterial blur, and Otsu's threshold
image = cv2.imread('1.png')
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.bilateralFilter(gray,9,75,75)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Perform morpholgical operations
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10,10))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=1)
# Find distorted rectangle contour and draw onto a mask
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
rect = cv2.minAreaRect(cnts[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image,[box],0,(36,255,12),4)
cv2.fillPoly(mask, [box], (255,255,255))
# Find corners
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(mask,4,.8,100)
offset = 25
for corner in corners:
x,y = corner.ravel()
cv2.circle(image,(x,y),5,(36,255,12),-1)
x, y = int(x), int(y)
cv2.rectangle(image, (x - offset, y - offset), (x + offset, y + offset), (36,255,12), 3)
print("({}, {})".format(x,y))
cv2.imshow('image', image)
cv2.imshow('thresh', thresh)
cv2.imshow('close', close)
cv2.imshow('mask', mask)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)
注意:扭曲边界框的想法来自如何从模糊图像中找到扭曲矩形的准确角位置中的先前答案