OpenCV 对象检测 - 中心点
Posted
技术标签:
【中文标题】OpenCV 对象检测 - 中心点【英文标题】:OpenCV Object Detection - Center Point 【发布时间】:2010-09-21 17:16:39 【问题描述】:给定一个纯白色背景上的对象,有人知道 OpenCV 是否提供了从捕获的帧中轻松检测对象的功能吗?
我正在尝试定位对象(矩形)的角/中心点。我目前正在这样做的方式是通过蛮力(扫描图像以查找对象)并且不准确。我想知道引擎盖下是否有我不知道的功能。
编辑详细信息: 大小和一个小汽水罐差不多。相机位于对象上方,以赋予其 2D/矩形的感觉。来自相机的方向/角度是随机的,由角点计算得出。
它只是一个白色背景,上面有对象(黑色)。拍摄的质量与您希望从罗技网络摄像头看到的一样。
一旦我得到角点,我就会计算中心。然后将中心点转换为厘米。
我正在努力专注于“如何”获得这 4 个角。你可以用这张图看到我的蛮力方法:Image
【问题讨论】:
【参考方案1】:由于没有人发布完整的 OpenCV 解决方案,这里有一个简单的方法:
获取二值图像。我们加载图像,转换为灰度,然后使用Otsu's threshold获取二值图像
寻找外轮廓。我们使用findContours
寻找轮廓,然后使用boundingRect
提取边界框坐标
求中心坐标。既然有了轮廓,就可以用moments提取轮廓的质心来求中心坐标
这是一个边界框和中心点以绿色突出显示的示例
输入图片->
输出
Center: (100, 100)
Center: (200, 200)
Center: (300, 300)
回顾一下:
给定一个纯白色背景上的对象,有人知道 OpenCV 是否提供了从捕获的帧中轻松检测对象的功能吗?
首先获取二值图像(Canny edge detection、simple thresholding、Otsu's threshold 或Adaptive threshold),然后使用findContours
找到轮廓。要获得边界矩形坐标,您可以使用boundingRect
,它将以x,y,w,h
的形式为您提供坐标。要绘制矩形,您可以使用rectangle
绘制它。这将为您提供轮廓的 4 个角点。如果您想获得中心点,请使用
moments
提取轮廓的质心
代码
import cv2
import numpy as np
# Load image, convert to grayscale, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Find contours and extract the bounding rectangle coordintes
# then find moments to obtain the centroid
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
# Obtain bounding box coordinates and draw rectangle
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
# Find center coordinate and draw center point
M = cv2.moments(c)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
cv2.circle(image, (cx, cy), 2, (36,255,12), -1)
print('Center: (, )'.format(cx,cy))
cv2.imshow('image', image)
cv2.waitKey()
【讨论】:
【参考方案2】:希望这有帮助,使用矩方法来获取黑白图像的质心。
cv::Point getCentroid(cv::Mat img)
cv::Point Coord;
cv::Moments mm = cv::moments(img,false);
double moment10 = mm.m10;
double moment01 = mm.m01;
double moment00 = mm.m00;
Coord.x = int(moment10 / moment00);
Coord.y = int(moment01 / moment00);
return Coord;
【讨论】:
【参考方案3】:已经有一个如何在 OpenCV 中进行矩形检测的示例(查看 samples/squares.c),实际上非常简单。
这是他们使用的粗略算法:
0. rectangles <-
1. image <- load image
2. for every channel:
2.1 image_canny <- apply canny edge detector to this channel
2.2 for threshold in bunch_of_increasing_thresholds:
2.2.1 image_thresholds[threshold] <- apply threshold to this channel
2.3 for each contour found in image_canny U image_thresholds:
2.3.1 Approximate contour with polygons
2.3.2 if the approximation has four corners and the angles are close to 90 degrees.
2.3.2.1 rectangles <- rectangles U contour
不是他们正在做什么的确切音译,但它应该对你有所帮助。
【讨论】:
我正在做一个类似的项目。我是 OpenCV 的新手,请您发布源代码来执行这些步骤吗? 我相信您要查找的文件现在是 [OpenCV_proj_dir]/samples/cpp/squares.cpp。【参考方案4】:OpenCV 有大量函数可以帮助您实现这一目标。如果您使用 C#.NET 进行编程,请下载 Emgu.CV 以获取包含在库中的 C#.CV。
得到你想要的东西的一些方法:
像以前一样找到角落 - 例如“CornerHarris”OpenCV 函数
阈值图像并计算重心 - 请参阅http://www.roborealm.com/help/Center%20of%20Gravity.php ...这是我将使用的方法。您甚至可以在 COG 例程中执行阈值处理。即 cog_x += *imagePtr
找到图像的时刻以提供旋转、重心等 - 例如“时刻”OpenCV 功能。 (我没用过)
(编辑)AForge.NET 库具有角点检测功能以及示例项目 (MotionDetector) 和用于连接网络摄像头的库。我认为这将是最简单的方法,假设您使用的是 Windows 和 .NET。
【讨论】:
关于cvCornerHarris,你能详细说明它是如何使用的吗?据我所知,您创建了一个图像并运行 cvCornerHarris(image,cornerimg,blockSize(?),apertureSize(?))。而且,您如何从角落图像中提取信息? 据我所知,它的工作方式是对每个像素运行一个大小为 'apertureSize' 的 sobel 边缘检测器,通过 'blockSize' 像素组在周围的 'blockSize' 上运行。然后它使用一个公式对该区域中检测到的边缘进行评分。角将同时具有水平和垂直。 生成的图像与原始图像大小相同,除了最亮的像素对应。到最强的角落。选择比要检测的角更大的块大小 - 为您的图像尝试 5 或 7。选择apertureSize,再小一点——试试3。我自己没用过这个功能,说说怎么用吧【参考方案5】:在其他机器视觉库中通常称为blob分析。我还没用过opencv。
【讨论】:
以上是关于OpenCV 对象检测 - 中心点的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV⚠️高手勿入! 半小时学会基本操作 15⚠️ 对象测量