项目实例,在一个无人封闭的隔绝场景中,根据视觉判断物件的有无,通过机械手
进行物件分类提取,并且返回状态结果;
实际的场景是有一个类似采血的固件支架盘,上面很多采血管,采血管帽颜色可能不同,
也有可能支架盘上只有空位,没有放置采血管,需要机器操作。
图像的大小,支架和物件的位置、大小等等都基本保存一致不会经常的变化。
开始的思路是通过判断空位上的圆来做排除,遇到了局限性,比如光照不好的情况下,空位
并非是正常的圆,可能是缺的圆,而且因为视角的缘故,根本没法判断是圆了,于是只好放弃;
后来就进行二值化后判断多个圆,如果有多个圆的那应该是有物件的,二值化后显然无法
根据颜色来判断不同的提取对象,也是不行的;
最后还是觉得通过颜色来判断比较合理,因为不仅仅要获取物件的有无,还要判断物件的分类,
而且物件的大概位置不能错,因为要知道对应的位置上是否有插物件。
设计思路:
使用 HSV颜色模型来做。
HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间,
也称六角锥体模型(Hexcone Model)。
HSV颜色模型是指H、S、V三维颜色空间中的一个可见光子集,它包含某个颜色域的所有颜色。
每一种颜色都是由色相(Hue,简H),饱和度(Saturation,简S)和色明度(Value,简V)所表示的。
这个模型中颜色的参数分别是:色调(H),饱和度(S),亮度(V)。
色调H参数表示色彩信息,即所处的光谱颜色的位置。该参数用一角度量来表示,取值范围为0°~360°。
若从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。
它们的补色是:黄色为60°,青色为180°,紫色为300°;
饱和度S:取值范围为0.0~1.0;
亮度V:取值范围为0.0(黑色)~1.0(白色)。
调试判断过程如下:
橘红色物件
黄色物件
相关代码如下
cpp
void CMFCCVMDlg::OnBnClickedBtnOpen()
{
char* window_name = "testCELL";
//resizeWindow(window_name, 480, 320);
BOOL isOpen = TRUE; //是否打开(否则为保存)
CString defaultDir = ""; //默认打开的文件路径
CString fileName = ""; //默认打开的文件名
CString filter = "图像文件 (*.png; *.jpg; *.bmp)|*.png;*.jpg;*.bmp||"; //文件过虑的类型
CFileDialog openFileDlg(isOpen, defaultDir, fileName, OFN_HIDEREADONLY | OFN_READONLY, filter, NULL);
openFileDlg.GetOFN().lpstrInitialDir = "";
INT_PTR result = openFileDlg.DoModal();
CString filePath = "";
if (result != IDOK)
{
//filePath = openFileDlg.GetPathName();
return;
}
filePath = openFileDlg.GetPathName();
Mat imgOriginal = imread(filePath.GetBuffer());
namedWindow("imgOriginal", 0);
imshow("imgOriginal", imgOriginal);
int iLowH = 0, iLowS = 0, iLowV = 0;
int iHighH = 180, iHighS = 255, iHighV = 255;
Mat imgHSV, imgThresholded;
//vector<Mat> hsvSplit;
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
//split(imgHSV, hsvSplit);
namedWindow(window_name, 0);
// 创建跟踪条并将其附着到指定窗口。
createTrackbar("iLowH:", window_name, &iLowH, 180); //no name cann't use this
createTrackbar("iHighH:", window_name, &iHighH, 180);
createTrackbar("iLowS:", window_name, &iLowS, 255);
createTrackbar("iHighS:", window_name, &iHighS, 255);
createTrackbar("iLowV:", window_name, &iLowV, 255);
createTrackbar("iHighV:", window_name, &iHighV, 255);
while (true)
{
// 检查数组元素是否位于其他两个数组的元素之间。
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded);
//src.copyTo(dst, detected_edges);
imshow(window_name, imgThresholded);
char key = (char)waitKey(30);
if (key == 27)
break;
}
}
最后做下亮块大小判断即可获得是否有物件,和对应位置,以及是什么颜色的物件。