python - 检测具有模糊边缘和不同背景的卡片边缘
问题描述
这是我的测试照片
我试图找到卡片的边缘。但是,如您所见,边缘有些模糊。
为了找到边缘,我首先增强了图像的对比度,因此希望模糊的边缘不会那么模糊,并且更容易找到: 然后我使用高斯模糊对其进行了一点平滑(我尝试去除高斯模糊,但边缘检测器发现到背景中的许多细节+卡片中的许多细节)。
然后我使用带有“动态阈值”的canny并得到以下结果: 如您所见,我大麦找到了卡片的任何边缘(除了左边的边缘,因为背景很暗,这很容易)。是否有一种强大的(我不想在此图像上“过度拟合”)方法来找到直的模糊边缘?
在这里找到了一些建议: 模糊边缘检测 如何从 python 中的模糊图像中找到扭曲矩形的准确角位置?,但没有一个导致令人满意的边缘。
完整代码:
def auto_canny(image, sigma=0.5):
v = np.median(image)
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
return cv2.Canny(image, lower, upper)
def add_contrast(img, contrast_level=8):
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(contrast_level, contrast_level))
cl = clahe.apply(l)
limg = cv2.merge((cl, a, b))
final = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
return final
# ------------------------------------------ #
# FIND EDGES
# ------------------------------------------ #
img = add_contrast(img=img, contrast_level=8)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)
edges = auto_canny(image=blur_gray)
# Show images for testing
cv2.imshow('edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
解决方案
这也不是一个完整的解决方案,但如果红色部分有问题,您可以先使用cv2.inpaint()
函数修复这些部分。然后,您可以应用其余方法来查找卡片边缘。
# create an inpainting mask with "red-enough" pixels
mask = cv2.inRange(img_src_rgb, np.array([200,0,0]), np.array([255,50,50]))
# enlarge the mask to cover the borders
kernel = np.ones((3,3),np.uint8)
mask = cv2.dilate(mask,kernel,iterations = 1)
# inpaint the red parts using Navier-Stokes based approach
img_dst = cv2.inpaint(img_src, mask,50,cv2.INPAINT_NS)
cv2.imshow("no_red", img_dst)
结果图像如下。
编辑:现在我们知道你在问什么,下面是一个完整的解决方案。
修复后,您可以应用霍夫变换来查找图像中的强直线。
gray = cv2.cvtColor(img_dst, cv2.COLOR_RGB2GRAY)
edges = auto_canny(gray) # your auto_canny function, WITHOUT blur
lines = cv2.HoughLines(edges, 1, np.pi/90, 50)
for line in lines:
rho,theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 10000*(-b))
y1 = int(y0 + 10000*(a))
x2 = int(x0 - 10000*(-b))
y2 = int(y0 - 10000*(a))
cv2.line(img_dst,(x1,y1),(x2,y2),(0,255,0),1)
cv2.imwrite('linesDetected.jpg', img_dst)
同样,结果行如下。
推荐阅读
- c# - 如何避免 ef 以上业务逻辑类中的重复代码?
- javascript - EDGE 在显示键盘输入时滞后
- azure-devops - 用于自动化而不是个人访问令牌的用户
- python - 在 matplotlib 图中配置网格线
- c# - 如何实现接口返回带有空方法体的 IAsyncResult
- python - 为什么即使请求详细信息相同,MS 图形浏览器和我的 python 请求结果也会不同
- sabre - SABRE:创建 PNR API 错误:ERR.SP.PROVIDER_ERROR
- nginx - 防止谷歌索引“deny_all”=错误403
- javascript - Gridview文本框焦点在垂直
- reactjs - react-intl 和 babel 不会导出消息,预设错误