问题描述
我想预测图像中的矩形并仅使用 opencv python 将矩形绘制为框形。我使用以下代码进行预测和绘制矩形,但无法正常工作。
import numpy as np
import cv2
from PIL import Image
import sys
Path='D:\Artificial intelligence\Phyton'
filename='Test.png'
# Load image,grayscale,Gaussian blur,and Otsu's threshold
image = cv2.imread('D:\Artificial intelligence\Phyton\Img21122020113231AM.Jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray,190,255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Find contours and sort using contour area
cnts = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts,key=cv2.contourArea,reverse=True)
for c in cnts:
# Highlight largest contour
cv2.drawContours(image,[c],-1,(36,12),3)
break
cv2.imwrite(filename+'_Processingimage_color.jpg',image)
我的输入图像:
我的结果:
解决方法
对于形状检测,有一个名为 opencv-shape-detection 的很棒的教程。然而,教程中的预处理不会帮助您找到图像中的大盒子。您需要应用 adaptiveThreshold
而不是 threshold
。以下是步骤:
-
- 调整图像大小并计算比例
-
- 平滑图像
-
- 应用自适应阈值
-
- 找到并抓住轮廓。
-
- 计算周长和近似长度
-
- 如果长度等于 4(意味着正方形或矩形),则绘制轮廓。
-
第一步
- 我们调整了图像的大小,使计算和检测更容易。但是,我们还需要计算比率,以免丢失每个轮廓的中心。
-
第 2 步
-
第 3 步
-
第 4 步
- 以与使用不同层次参数相同的方式查找轮廓。见Contours-hierarchy
-
第 5 步
- 对于每个轮廓,计算周长和近似参数。见Contour-features
-
第 6 步
代码:
import cv2
import imutils
# Load the image
img = cv2.imread("zE2lg.jpg")
# Resize the image
rsz = imutils.resize(img,width=300)
# Calculate the ratio
ratio = img.shape[0] / float(rsz.shape[0])
# Convert to gray-scale
gry = cv2.cvtColor(rsz,cv2.COLOR_BGR2GRAY)
# Apply Gaussian-blur
blr = cv2.GaussianBlur(gry,0)
# Apply threshold
thr = cv2.adaptiveThreshold(blr,21)
# Find and grab contours
cnt = cv2.findContours(thr.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnt = imutils.grab_contours(cnt)
# Loop over contours
for c in cnt:
mmn = cv2.moments(c)
if mmn["m00"] != 0:
x = int((mmn["m10"] / mmn["m00"]) * ratio)
y = int((mmn["m01"] / mmn["m00"]) * ratio)
prm = cv2.arcLength(c,True) # perimeter
apx = cv2.approxPolyDP(c,0.09 * prm,True) # approximation
if len(apx) == 4:
c = c.astype("float")
c *= ratio
c = c.astype("int")
cv2.drawContours(img,[c],-1,(0,255),thickness=5)
,
按照以下步骤,您应该能够在此特定图像中检测到您的纸板箱。您应该能够使用 numpy 和 OpenCV 完成所有这些工作。不过这将是很多工作,所以我还没有完成。如果其他人想通过它并提供源代码,请随时将他们的答案标记为正确的答案而不是这个答案。
- 将图像的副本转换为 HSV 色彩空间。
- 检测您的纸板颜色,如深橙色或深黄色。如果 HSV 范围是 0-360、0-255、0-255,那么您想要检测的颜色范围将在 20-60、20-255、20-100 左右。
- 将结果转换为二维黑白图像。
- 使用较小的内核大小执行形态腐蚀以消除嘈杂的斑点。也许内核大小约为 3x3。
- 使用大内核大小执行形态学扩张,以连接任何断开连接的区域。也许内核大小约为 20x20。
- 找到最大的轮廓对象。
- 将轮廓转换为最适合的四边形,以去除右侧较小的纸板箱。我有时发现在将轮廓转换为四边形之前先将其转换为凸包会很有帮助。
- 在原始图像上绘制四边形。或者把它剪掉。或者您想用它做什么。
此 stackoverflow 帖子将有助于第 7 步: How to force approxPolyDP() to return only the best 4 corners? - Opencv 2.4.2
可以在此处找到我上面概述的方法的另一种替代潜在解决方案(在检测到棕色纸板颜色后): Extracting the dimensions of a rectangle