问题描述
我正在尝试找到墨迹斑点角落的准确位置,如下所示:
I am trying to find accurate locations for the corners on ink blotches as seen below:
我的想法是使线条适合边缘,然后找到它们相交的位置.到目前为止,我已经尝试将cv2.approxPolyDP()与epsilon的各种值一起使用来近似边缘,但是这看起来并不可行.我的cv.approxPolyDP代码给出以下结果:
My idea is to fit lines to the edges and then find where they intersect. As of now, I've tried using cv2.approxPolyDP() with various values of epsilon to approximate the edges, however this doesn't look like the way to go. My cv.approxPolyDP code gives the following result:
理想情况下,这就是我要生产的(用油漆绘制):
Ideally, this is what I want to produce (drawn on paint):
是否存在解决此类问题的CV功能?我已经考虑过在阈值步骤之前使用高斯模糊,尽管该方法似乎对于拐角查找似乎并不十分准确.此外,我希望它对旋转图像具有较强的鲁棒性,因此,在没有其他考虑的情况下,对垂直线和水平线的过滤不一定会起作用.
Are there CV functions in place for this sort of problem? I've considered using Gaussian blurring before the threshold step although that method does not seem like it would be very accurate for corner finding. Additionally, I would like this to be robust to rotated images, so filtering for vertical and horizontal lines won't necessarily work without other considerations.
代码*:
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()
- 关于我的代码的注释:我正在使用屏幕捕获,以便可以实时处理这些图像.我有一台可以在屏幕上显示实时供稿的数字显微镜,因此连续的屏幕记录使我可以从视频供稿中采样并在屏幕的另一半上找到实时的边角.
- A note about my code: I'm using screen capture so that I can process these images live. I have a digital microscope that can display live feed on a screen, so the constant screen recording will allow me to sample from the video feed and locate the corners live on the other half of my screen.
Obtain binary image. We load the image, blur with bilateral filter, grayscale, then Otsu's threshold
推荐答案
以下是使用阈值+ 形态学操作:
形态学操作.我们执行一系列形态学的打开和关闭操作,以平滑图像并消除噪声
Morphological operations. We perform a series of morphological open and close to smooth the image and remove noise
以下是每个步骤的可视化结果:
Here's a visualization of each step:
二进制图像->
形态学操作->
近似蒙版->
检测到的角
Binary image ->
Morphological operations ->
Approximated mask ->
Detected corners
这是拐角坐标:
(103, 550)
(1241, 536)
这是其他图像的结果
(558, 949)
(558, 347)
最后显示旋转的图像
(201, 99)
(619, 168)
代码
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()
注意:扭曲边框的想法来自
Note: The idea for the distorted bounding box came from a previous answer in How to find accurate corner positions of a distorted rectangle from blurry image
这篇关于将锯齿状的边缘近似为线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!