OpenCV:找不到大矩形轮廓
OpenCV: Can't find large rectangle contour
Opencv 版本:4.5
我正在尝试通过将对象设置在网格上并拍摄尽可能接近自上而下的照片来重新创建对象的尺寸,然后我将获得最大边界矩形的轮廓和然后透视扭曲。
我目前无法获得大边界正方形的轮廓,但是,它不断地只找到较小的 rectangles/squares,我假设它不够大,无法正确修复视角。
第一张图片:原图
第二张图片:我使用 openCV 从我的代码中得到了什么
第三张图片:接近我理想中的效果
我的代码:
import imutils
import numpy as np
import cv2 as cv
# load the query image
image = cv.imread("path/to/image")
# make image greyscale, blur, find edges
grayscale_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
thresh = cv.adaptiveThreshold(grayscale_image, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C,
cv.THRESH_BINARY, 11, 2)
# find contours in the threshed image, keep only the largest
# ones
cnts = cv.findContours(
thresh.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key=cv.contourArea, reverse=True)[:5]
# draw contours for reference
cv.drawContours(image, cnts, -1, (0, 255, 0), 3)
我尝试使用双边滤波器或高斯模糊进行精细边缘检测,而不是预处理的自适应阈值,但结果仍然找不到大矩形。
任何帮助将不胜感激,因为我不知道为什么它不能检测到更大的方块。另外,如果人们认为有更好的方法来固定视角以便我可以准确地重新创建电路板尺寸,请告诉我。
您可以申请以下阶段:
- 使用
cv2.threshold
(而不是 cv2.adaptiveThreshold
)应用阈值。
- 应用长列向量开洞以仅保留垂直线。
- 在
vert_lines
中查找轮廓。
- 从左到右对轮廓进行排序。
- 在草图(黑色)图像上绘制最左边和最右边的轮廓。
- 应用长行向量开孔以仅保留水平线、查找等高线、从上到下排序并绘制顶部和底部等高线。
- 在素描图像中找出内部轮廓(用左、右、顶、底线)。
内轮廓是最小的。
这是一个代码示例:
import imutils
import numpy as np
import cv2
# load the query image
image = cv2.imread("image.png")
# make image greyscale, blur, find edges
grayscale_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#thresh = cv2.adaptiveThreshold(grayscale_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
thresh = cv2.threshold(grayscale_image, 0, 255, cv2.THRESH_OTSU)[1] # Apply automatic threshold (use THRESH_OTSU).
rect_im = np.zeros_like(thresh) # Sketch image
# Apply opening with long column vector for keeping only the vertical lines.
vert_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones(50))
# Apply opening with long row vector for keeping only the horizontal lines.
horz_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones((1,50)))
# Find contours in vert_lines
cnts = imutils.grab_contours(cv2.findContours(vert_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE))
# Sort contours left to right.
cnts = sorted(cnts, key=lambda c: cv2.boundingRect(c)[0]) # cv2.boundingRect(c)[0] is the left side x coordinate.
cv2.drawContours(rect_im, [cnts[0], cnts[-1]], -1, 255, -1) # Draw left and right contours
# Find contours in horz_lines
cnts = imutils.grab_contours(cv2.findContours(horz_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE))
# Sort contours top to bottom.
cnts = sorted(cnts, key=lambda c: cv2.boundingRect(c)[1]) # cv2.boundingRect(c)[1] is the top y coordinate.
cv2.drawContours(rect_im, [cnts[0], cnts[-1]], -1, 255, -1) # Draw top and bottom contours
# Find contours in rect_im
cnts = imutils.grab_contours(cv2.findContours(rect_im, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)) # Note: use RETR_TREE for getting inner contour.
c = min(cnts, key=cv2.contourArea) # Get the smallest contour
# Draw contour for reference
cv2.drawContours(image, [c], -1, (0, 255, 0), 3)
结果:
thresh
:
vert_lines
:
horz_lines
:
左右行数:
rect_im
:
image
(输出):
Opencv 版本:4.5
我正在尝试通过将对象设置在网格上并拍摄尽可能接近自上而下的照片来重新创建对象的尺寸,然后我将获得最大边界矩形的轮廓和然后透视扭曲。
我目前无法获得大边界正方形的轮廓,但是,它不断地只找到较小的 rectangles/squares,我假设它不够大,无法正确修复视角。
第一张图片:原图
第二张图片:我使用 openCV 从我的代码中得到了什么
第三张图片:接近我理想中的效果
我的代码:
import imutils
import numpy as np
import cv2 as cv
# load the query image
image = cv.imread("path/to/image")
# make image greyscale, blur, find edges
grayscale_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
thresh = cv.adaptiveThreshold(grayscale_image, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C,
cv.THRESH_BINARY, 11, 2)
# find contours in the threshed image, keep only the largest
# ones
cnts = cv.findContours(
thresh.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key=cv.contourArea, reverse=True)[:5]
# draw contours for reference
cv.drawContours(image, cnts, -1, (0, 255, 0), 3)
我尝试使用双边滤波器或高斯模糊进行精细边缘检测,而不是预处理的自适应阈值,但结果仍然找不到大矩形。
任何帮助将不胜感激,因为我不知道为什么它不能检测到更大的方块。另外,如果人们认为有更好的方法来固定视角以便我可以准确地重新创建电路板尺寸,请告诉我。
您可以申请以下阶段:
- 使用
cv2.threshold
(而不是cv2.adaptiveThreshold
)应用阈值。 - 应用长列向量开洞以仅保留垂直线。
- 在
vert_lines
中查找轮廓。 - 从左到右对轮廓进行排序。
- 在草图(黑色)图像上绘制最左边和最右边的轮廓。
- 应用长行向量开孔以仅保留水平线、查找等高线、从上到下排序并绘制顶部和底部等高线。
- 在素描图像中找出内部轮廓(用左、右、顶、底线)。
内轮廓是最小的。
这是一个代码示例:
import imutils
import numpy as np
import cv2
# load the query image
image = cv2.imread("image.png")
# make image greyscale, blur, find edges
grayscale_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#thresh = cv2.adaptiveThreshold(grayscale_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
thresh = cv2.threshold(grayscale_image, 0, 255, cv2.THRESH_OTSU)[1] # Apply automatic threshold (use THRESH_OTSU).
rect_im = np.zeros_like(thresh) # Sketch image
# Apply opening with long column vector for keeping only the vertical lines.
vert_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones(50))
# Apply opening with long row vector for keeping only the horizontal lines.
horz_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones((1,50)))
# Find contours in vert_lines
cnts = imutils.grab_contours(cv2.findContours(vert_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE))
# Sort contours left to right.
cnts = sorted(cnts, key=lambda c: cv2.boundingRect(c)[0]) # cv2.boundingRect(c)[0] is the left side x coordinate.
cv2.drawContours(rect_im, [cnts[0], cnts[-1]], -1, 255, -1) # Draw left and right contours
# Find contours in horz_lines
cnts = imutils.grab_contours(cv2.findContours(horz_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE))
# Sort contours top to bottom.
cnts = sorted(cnts, key=lambda c: cv2.boundingRect(c)[1]) # cv2.boundingRect(c)[1] is the top y coordinate.
cv2.drawContours(rect_im, [cnts[0], cnts[-1]], -1, 255, -1) # Draw top and bottom contours
# Find contours in rect_im
cnts = imutils.grab_contours(cv2.findContours(rect_im, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)) # Note: use RETR_TREE for getting inner contour.
c = min(cnts, key=cv2.contourArea) # Get the smallest contour
# Draw contour for reference
cv2.drawContours(image, [c], -1, (0, 255, 0), 3)
结果:
thresh
:
vert_lines
:
horz_lines
:
左右行数:
rect_im
:
image
(输出):