我有一系列图片。我在这里发布了一个示例图片。 我需要从图像中提取特征作为每个图像上绘制的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;
}
答案 0 :(得分:5)
使用与您相似的代码很容易找到所有标记 - 您只需要将图像转换为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),所以如果你读取例如颜色(a,b,c) )从屏幕的底部,你应该使用标量(c,a,b)。
inRange之后的结果:
最终结果:
正如您所看到的,图像上还有其他对象,但应该易于检测和擦除 - 只需在带有面部的区域(使用面部检测)中查找标记,或者只是为每个轮廓找到它的边界并检查百分比的百分比边界矩形区域是轮廓区域 - 如果此值小于丢弃此轮廓(因为它与圆形不相似)。
答案 1 :(得分:3)
对于这样的问题,可能有多种解决方案可以完成您想要做的事情。您可以使用OpenCV来帮助您自己实现这些功能。关于如何处理这类问题的一些建议:
这还取决于一些事情。看起来这张图片中的衬衫有很多蓝色,所以它可能会被标记分割。要删除它,您可以使用OpenCV的面部检测来查找面部,然后只担心找到的面部区域。
还取决于你是否知道鼻子标记在哪里。如果您可以手动选择它(可以使用OpenCV执行此操作),您可以在鼻子标记上设置种子,然后执行前面的步骤。
如果您无法手动选择它,根据此图像显示鼻子标记靠近图像的中心(如果您使用的是鼻尖)。您可能能够找到最接近图像中心的质心并使用它。这样做取决于你要测试的其他图像。此外,这种确定鼻子标记的自动方法可能不起作用,因为还有其他标记非常接近。您可以选择其中一个而不是实际的鼻尖。
正如我所说,这是一个非常主观的问题,可能有很多解决方案可以解决它。这些只是一些建议,可能有助于指明您正确的方向。