【问题标题】:How do we detect points from a picture with a particular color on those points我们如何从这些点上具有特定颜色的图片中检测点
【发布时间】:2013-09-12 18:12:12
【问题描述】:

我有一系列图像。我在这里发布示例图片。 我需要从图像中提取特征作为绘制在每个图像上的 60 个标记的坐标。然后从一个特定的标记(在鼻子上)我需要找到所有其他标记的距离。

我试图使用 openCV 作为语言来完成此任务并正在阅读文档,但一周后我仍然无法实现目标。谁能指导我正确的方向。如果不是整个解决方案,请给我一个链接或教程,让我了解如何完成它。

请参考我上传的图片。标记在整个图像上涂成蓝色。

任何帮助将不胜感激。谢谢。

这是我尝试过的代码,但结果严重偏离了轨道。

     //This function threshold the HSV image and create a binary image
Mat GetThresholdedImage(Mat imgRGB){        
    Mat imgThresh;   
    inRange(imgRGB, Scalar(95,110,151), Scalar(112,125,169), imgThresh); 
    return imgThresh;
} 
int main(){
 Mat frame;
 frame = imread("other/test2.jpeg");
 namedWindow("Input");      
 namedWindow("Ball");

 Mat imgRGB=frame.clone();

 Mat imgThresh = GetThresholdedImage(imgRGB);


 imshow("Ball", imgThresh);            
 imshow("Input", frame);

 waitKey(0);
 return 0;
}

【问题讨论】:

  • 看看question有一些很好的切入点和示例!

标签: c++ opencv image-processing


【解决方案1】:

使用与您类似的代码很容易找到所有标记 - 您只需将图像转换为 HSV 颜色空间,而不是使用 inRange 函数 - HSV 颜色空间更适合此类任务,因为它“关注”颜色,而不是关于亮度。这段代码:

Mat m = imread("D:\\face.jpg"), m2, m3;
cvtColor(m, m, CV_RGB2HSV);
resize(m, m, Size(m.cols/2, m.rows/2));
inRange(m, Scalar(0, 90, 50), Scalar(15, 175, 190), m2); 
imshow("qwe", m);
imshow("qwe2", m2);
dilate(m2, m3, Mat());
imshow("qwe", m);
imshow("qwe2", m2);
imshow("qwe3", m3);
waitKey(-1);
return 0;

关于这段代码的几件事:
- 当然,您必须更改文件路径
- 调整大小并不重要 - 我只使用过它,因为图像对于我的屏幕来说太大了
- 可以通过查看 HSV 中显示的图像轻松找到 inRange 标量的值(OpenCV 将具有 3 个通道的每个图像显示为 RGB 图像,因此看起来有点奇怪) - 只需从窗口底部读取值(可能你有为此使用 QT 构建 OpenCV,否则窗口将没有此信息): 注意 - 值的顺序不同于通常(HSV),因此如果您从在屏幕底部,您应该使用 Scalar(c, a, b)。

inRange 之后的结果:
最终结果:

如您所见,图像上还有其他对象,但应该很容易检测和擦除 - 只需在有面部的区域中查找标记(使用面部检测)或简单地为每个轮廓找到它的边界矩形并检查百分比边界矩形区域是轮廓区域 - 如果此值小于删除此轮廓(因为它与圆形不同)。

【讨论】:

  • 非常感谢西里尔。这真的很有帮助。
  • 我只有一个问题。我如何找到范围。我尝试使用 HSV,但我无法获得正确的范围。很抱歉,我在一个单独的项目中被捆绑了这么晚的回复。
  • 您可以从窗口底部读取它(标记在第一张图像上),也可以创建简单的应用程序,其中包含 H、S、V 上下边界的 6 个滑块,并使用它手动查找边界。
  • 我可以对所有检测到的区域进行编号吗?
  • 我不确定你在问什么,但可能只需要使用函数 findContours - docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/…
【解决方案2】:

对于这样的问题,可能有多种解决方案来完成您想做的事情。您可以使用 OpenCV 来帮助您自己实现这些功能。关于如何处理此类问题的一些建议:

  1. 从图像中分割出蓝色标记。可能使用蓝色通道上的阈值来获得这些点。它们在蓝色通道中应该具有相当高的价值。
  2. 由于标记看起来不止一个像素,您可以将附近的蓝色相邻像素视为一个簇,并找到每个簇(标记)的质心。
  3. 从鼻尖的质心,计算到面部每个聚类质心的距离。

这也取决于一些事情。看起来这张图片中的衬衫有相当多的蓝色,所以它可能会被标记分割。要删除它,您可以使用 OpenCV 的人脸检测来查找人脸,然后只需担心找到的人脸区域。

还取决于您是否知道鼻子标记在哪里。如果您可以手动选择它(可以使用 OpenCV 来执行此操作),您可以在鼻子标记上设置一个种子,然后执行前面的步骤。

如果您无法手动选择它,则根据此图像,鼻子标记似乎靠近图像的中心(如果您使用的是鼻尖)。您可能能够找到最接近图像中心的质心并使用它。这样做将取决于您将要测试的其余图像。此外,这种确定鼻子标记的自动方法可能不起作用,因为还有其他非常接近的标记。您可以选择其中一个来代替实际的鼻尖。

正如我所说,这是一个非常主观的问题,可以有很多解决方案来解决它。这些只是一些建议,也许可以帮助您指明正确的方向。

【讨论】:

  • 也许您可以使用霍夫变换将蓝色标记检测为圆形 - 因此您不需要使用人脸检测。
  • 非常感谢您回答 bruvei。生病尝试解决方案。我知道这个问题意味着我没有做好我的背景工作,但我只是不知道如何开始。
  • @retinotop 请您详细说明一下。我需要找到蓝色标记的坐标才能找到距离。
  • @bruvel 我试着按照你告诉我的去做。我设置了一个阈值并试图检测这些区域。但结果严重偏离轨道。我会在上面的问题中分享我的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-29
  • 2021-11-01
  • 2023-01-12
  • 2021-07-20
  • 2019-11-03
  • 2018-06-23
  • 1970-01-01
相关资源
最近更新 更多