我打算编写一个程序,从几乎纯色的背景中检测和区分特定对象。前景和背景之间具有高对比度差异,我将进一步增加差异以帮助对象识别过程。我计划使用Hough变换技术和OpenCV。
如上图所示,我想要单独识别圆形对象和正方形对象(或有限形状集中的任何其他形状)。由于我在图像处理方面相当新手,我不知道这种情况是否需要实现神经网络并预先学习每个形状。使用模板匹配这样的技术能否让我在没有神经网络的情况下完成此操作?
我打算编写一个程序,从几乎纯色的背景中检测和区分特定对象。前景和背景之间具有高对比度差异,我将进一步增加差异以帮助对象识别过程。我计划使用Hough变换技术和OpenCV。
如上图所示,我想要单独识别圆形对象和正方形对象(或有限形状集中的任何其他形状)。由于我在图像处理方面相当新手,我不知道这种情况是否需要实现神经网络并预先学习每个形状。使用模板匹配这样的技术能否让我在没有神经网络的情况下完成此操作?
如果您想检测除圆外的其他形状(这张图像似乎是这样),我建议使用Chamfer匹配进行快速起步,特别是因为您有很好的对比度。
基本原理简单说明如下:
cvCanny
)这种基本方法是一种通用解决方案,通常效果很好,但没有进一步的改进,它非常慢。
通常,首先分离感兴趣的对象是一个好主意,这样您就不必始终在整个图像上执行完整搜索。找到一个好的threshold
,以便您可以分离对象。您仍然不知道它是哪个对象,但只需在该对象附近进行匹配本身即可。
另一个好主意是,而不是在高分辨率图像上进行完整搜索,先在非常低的分辨率上进行搜索。结果可能不是很准确,但您可以知道值得在更高的分辨率上进行搜索的一般区域,因此您不会浪费时间在没有兴趣的区域上。
还有许多更先进的技术,但仍然值得看一下基本的chamfer匹配,因为它是许多技术的基础。
假设对象是简单形状,这里介绍一种使用阈值处理和轮廓逼近的方法。轮廓逼近基于曲线可以用一系列短线段来近似的假设,这些线段可以用来确定轮廓的形状。例如,三角形有三个顶点,正方形/矩形有四个顶点,五边形有五个顶点,以此类推。
获取二进制图像。 我们加载图像,转换为灰度图,进行高斯模糊,然后使用 自适应阈值 来获取二进制图像。
检测形状。 查找轮廓并使用轮廓近似过滤器识别每个轮廓的形状。这可以使用 arcLength
计算轮廓的周长,使用 approxPolyDP
获取实际的轮廓近似来完成。
输入图像
检测出的对象以绿色突出显示
标记轮廓
代码
import cv2
def detect_shape(c):
# Compute perimeter of contour and perform contour approximation
shape = ""
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.04 * peri, True)
# Triangle
if len(approx) == 3:
shape = "triangle"
# Square or rectangle
elif len(approx) == 4:
(x, y, w, h) = cv2.boundingRect(approx)
ar = w / float(h)
# A square will have an aspect ratio that is approximately
# equal to one, otherwise, the shape is a rectangle
shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
# Star
elif len(approx) == 10:
shape = "star"
# Otherwise assume as circle or oval
else:
shape = "circle"
return shape
# Load image, grayscale, Gaussian blur, and adaptive threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (7,7), 0)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,31,3)
# Find contours and detect shape
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
# Identify shape
shape = detect_shape(c)
# Find centroid and label shape name
M = cv2.moments(c)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
cv2.putText(image, shape, (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (36,255,12), 2)
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()