首页 > 解决方案 > 广告牌角点检测

问题描述

我试图检测随机背景上的广告牌图像。我能够使用 SSD 定位广告牌,这给了我广告牌周围的近似边界框。现在我想为我的应用程序找到广告牌的确切角落。我尝试使用我遇到的不同策略,例如 Harris 角点检测(使用 Opencv),使用 Canny + 形态学操作 + 轮廓查找线的交点。下面给出了输出的详细信息。

哈里斯角点检测哈里斯角点检测 的伪代码如下:

img_patch_gray = np.float32(img_patch_gray)
harris_point = cv2.cornerHarris(img_patch_gray,2,3,0.04)
img_patch[harris_point>0.01*harris_point.max()]=[255,0,0]
plt.figure(figsize=IMAGE_SIZE)
plt.imshow(img_patch)

哈里斯检测结果 这里红点是Harris角点检测算法检测到的角点,兴趣点被绿色包围。

使用霍夫线检测 在这里我试图找到线的交点,然后选择点。类似于stackoverflow 链接的东西,但由于广告牌中有文本和图形,因此很难获得准确的线条。

基于轮廓 在这种方法中,我使用了精明的边缘检测器,然后是膨胀(3*3 内核),然后是轮廓。

bin_img = cv2.Canny(gray_img_patch,100,250)
bin_img = dilate(bin_img, 3)
plt.imshow(bin_img, cmap='gray')
(_,cnts, _) = cv2.findContours(bin_img.copy(), 
cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:10]
cv2.drawContours(img_patch, [cnts[0]],0, (0,255,0), 1)

拨号后的二值化图像, 检测到的最大轮廓. 我曾尝试使用 openCV 中的 approxPolyDp 函数,但它并不像预期的那样,因为它还可以通过四个点来近似更大或更小的轮廓,并且在某些图像中它可能不会在广告牌框架周围形成轮廓。

我已将 openCV 3.4 用于所有图像处理操作。原始图像可以在这里找到使用过的。请注意,此处讨论的图像仅用于说明目的,一般图像可以是任何广告牌。在此先感谢,任何帮助表示赞赏。

标签: opencvimage-processingcomputer-visioncorner-detection

解决方案


这是一项非常困难的任务,因为图像包含大量噪声。您可以获得轮廓的近似值,但特定的角落会非常困难。我举了一个例子来说明我将如何做一个近似值。它可能不适用于其他图像。也许它会有所帮助或给你一个新的想法。干杯!

import cv2
import numpy as np

# Read the image
img = cv2.imread('billboard.png')

# Blur the image with a big kernel and then transform to gray colorspace
blur = cv2.GaussianBlur(img,(19,19),0)
gray = cv2.cvtColor(blur,cv2.COLOR_BGR2GRAY)

# Perform histogram equalization on the blur and then perform Otsu threshold
equ = cv2.equalizeHist(gray)
_, thresh = cv2.threshold(equ,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Perform opening on threshold with a big kernel (erosion followed by dilation)
kernel = np.ones((20,20),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# Search for contours and select the biggest one
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)

# Make a hull arround the contour and draw it on the original image
mask = np.zeros((img.shape[:2]), np.uint8)
hull = cv2.convexHull(cnt)
cv2.drawContours(mask, [hull], 0, (255,255,255),-1)

# Search for contours and select the biggest one again
_, thresh = cv2.threshold(mask,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)

# Draw approxPolyDP on the image
epsilon = 0.008*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
cv2.drawContours(img, [cnt], 0, (0,255,0), 5)

# Display the image
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

在此处输入图像描述


推荐阅读