Rob*_*505 5 python opencv image image-processing corner-detection
我正在寻找一个程序,可以使用 Python 中的 OpenCV 准确检测扭曲矩形的角点。
我已经尝试通过谷歌搜索来解决不同的建议,但是通过直线的正弦叠加(参见阈值图像)我可能无法检测到角点。到目前为止,我尝试了 findContours 和 HoughLines,但没有取得好的结果。不幸的是我不明白Xu Bin关于如何使用opencv找到模糊角位置的C代码?
这是我的初始图像:
调整大小和阈值后,我应用精明的边缘检测来获得以下图像:

contours, hierarchy = cv2.findContours(g_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
box = cv2.minAreaRect(contour)
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
box = np.array(box, dtype="float")
box = perspective.order_points(box)
Run Code Online (Sandbox Code Playgroud)
我仅通过一些额外的绘图得到以下结果:

我认为直线拟合是解决问题的好方法,但不幸的是我无法让 HoughLines 工作,并且在查看OpenCV Python - How to Implement RANSAC to detector Straightlines?之后我无法让 HoughLines 工作。RANSAC似乎也很难适用于我的问题。
非常感谢任何帮助。
虽然这已经很旧了,但这至少可以帮助其他有同样问题的人。除了 nathancy 的答案之外,这应该可以让您更准确地找到非常模糊的角落:
img = cv2.resize(img, (img.shape[0] * 5, img.shape[1] * 5))
Run Code Online (Sandbox Code Playgroud)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Run Code Online (Sandbox Code Playgroud)
# choose one, or a different function
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
blurred = cv2.bilateralFilter(gray, 9, 75, 75)
Run Code Online (Sandbox Code Playgroud)
0和255作为阈值和最大值的参数。我们通过0是因为我们使用阈值技术cv2.THRESH_OTSU来确定我们的值。它与阈值本身一起返回,但我只是将其设置为_因为我们不需要它。_, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
Run Code Online (Sandbox Code Playgroud)
_,并且我们只需要它找到的单个轮廓,因此我们将其设置为contour = contours[0]。contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour = contours[0]
Run Code Online (Sandbox Code Playgroud)
cv2.approxPolyDP,并用 告诉它原始曲线与其近似值之间的最大距离0.05 * perimeter。您可能需要使用小数以获得更好的近似值。approx是一个具有 shape 的 numpy 数组(num_points, 1, 2),在本例中是(4, 1, 2)因为它找到了矩形的 4 个角。请随意阅读文档中的更多内容。
perimeter = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.05 * perimeter, True)
Run Code Online (Sandbox Code Playgroud)
# drawing points
for point in approx:
x, y = point[0]
cv2.circle(img, (x, y), 3, (0, 255, 0), -1)
# drawing skewed rectangle
cv2.drawContours(img, [approx], -1, (0, 255, 0))
Run Code Online (Sandbox Code Playgroud)
import cv2
img = cv2.imread("rect.png")
img = cv2.resize(img, (img.shape[0] * 5, img.shape[1] * 5))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.bilateralFilter(gray, 9, 75, 75)
_, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour = contours[0]
perimeter = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.05 * perimeter, True)
for point in approx:
x, y = point[0]
cv2.circle(img, (x, y), 3, (0, 255, 0), -1)
cv2.drawContours(img, [approx], -1, (0, 255, 0))
Run Code Online (Sandbox Code Playgroud)
要检测角点,您可以使用cv2.goodFeaturesToTrack(). 该函数有四个参数
corners = cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance)
Run Code Online (Sandbox Code Playgroud)
image- 输入8位或浮点32位灰度单通道图像maxCorners- 返回的最大角数qualityLevel- 0-1 之间的角点的最低可接受质量水平。所有低于质量水平的角都被拒绝minDistance- 角点之间的最小可能欧几里得距离现在我们知道如何找到角点,我们必须找到旋转的矩形并应用该函数。这是一种方法:
我们首先放大图像,转换为灰度,应用双边滤波器,然后大津阈值得到二值图像

接下来,我们通过查找轮廓来找到扭曲的矩形,cv2.findContours()然后获得以绿色突出显示的旋转边界框。我们将这个边界框绘制到蒙版上

现在我们有了蒙版,我们只需用来cv2.goodFeaturesToTrack()查找蒙版上的角点

这是原始输入图像的结果和(x, y)每个角的坐标

角点
(377.0, 375.0)
(81.0, 344.0)
(400.0, 158.0)
(104.0, 127.0)
Run Code Online (Sandbox Code Playgroud)
代码
import cv2
import numpy as np
import imutils
# Resize image, blur, and Otsu's threshold
image = cv2.imread('1.png')
resize = imutils.resize(image, width=500)
mask = np.zeros(resize.shape, dtype=np.uint8)
gray = cv2.cvtColor(resize, cv2.COLOR_BGR2GRAY)
blur = cv2.bilateralFilter(gray,9,75,75)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Find distorted rectangle contour and draw onto a mask
cnts = cv2.findContours(thresh, 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(resize,[box],0,(36,255,12),2)
cv2.fillPoly(mask, [box], (255,255,255))
# Find corners on the mask
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(mask, maxCorners=4, qualityLevel=0.5, minDistance=150)
for corner in corners:
x,y = corner.ravel()
cv2.circle(resize,(x,y),8,(155,20,255),-1)
print("({}, {})".format(x,y))
cv2.imshow('resize', resize)
cv2.imshow('thresh', thresh)
cv2.imshow('mask', mask)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)