python - OpenCV:找不到大矩形轮廓
问题描述
Opencv版本:4.5
我试图通过将对象设置在网格上并尽可能接近自上而下的照片来重新创建对象的尺寸,然后我将获得最大边界矩形的轮廓,然后进行透视扭曲。
我目前无法获得大边界正方形的轮廓,但是,它不断地只找到较小的矩形/正方形,我认为这些矩形/正方形不够大,无法正确修复视角。
第一张图:原图
我的代码:
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)
结果:
推荐阅读
- javascript - 节点脚本到 console.log 并返回数据
- android - 如何在工具栏中显示不带后退按钮的设置活动
- python - 为什么python“in”语句会以这种方式评估?
- r - R:用更具描述性的值替换数据框列中的值
- swift - 在加载视图之前如何在 SwiftUI 中初始化值?
- c# - 使用 Automapper (C#) 将 JObject 转换为类的有效方法
- python - Python的sqlite3中自动关闭数据库
- java - 括号内特殊字符的正则表达式
- ruby-on-rails - 使用 Ruby on rails 您可以使用会话和身份验证(gem bcrypt)拥有多种用户类型吗?
- python - 从车牌中查找轮廓时出错 - fillConvexPoly