一、原理
- 根据提取的颜色HSV模板值做颜色识别
颜色提取的一种方式是将BGR空间下的图像转换为HSV空间下,然后利用opencv自带函数inRange,设置需提取的HSV各分量上下限,从而进行提取。 -
下面给出HSV对应BGR颜色的表格
二、InRange函数
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded);
- 这个函数的作用就是检测src图像的每一个像素是不是在lowerb和upperb之间,如果是,这个像素就设置为255,并保存在dst图像中,否则为0。
三、程序
private void button2_Click_1(object sender, EventArgs e)
{
// 黄色的HSV区间。也可换成上面提取的HSV颜色模板来识别颜色
int low_H = 26;
int high_H = 34;
int low_S = 43;
int high_S = 255;
int low_V = 46;
int high_V = 255;
Mat hsv_image = new Mat();
Cv2.CvtColor(src_img, hsv_image, ColorConversionCodes.BGR2HSV);
//因为我们读取的是彩色图,直方图均衡化需要在HSV空间做
Mat[] hsvSplit;
hsvSplit=Cv2.Split(hsv_image);
Cv2.EqualizeHist(hsvSplit[2], hsvSplit[2]);
Cv2.Merge(hsvSplit, hsv_image);
Mat imgThresholded = new Mat();
Cv2.InRange(hsv_image, new Scalar(low_H, low_S, low_V), new Scalar(high_H, high_S, high_V), imgThresholded);
//开操作 (去除一些噪点)
Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(5, 5) );
Cv2.MorphologyEx(imgThresholded, imgThresholded, MorphTypes.Open, element);
//闭操作 (连接一些连通域)
Cv2.MorphologyEx(imgThresholded, imgThresholded, MorphTypes.Close, element);
Cv2.ImShow("imgThresholded", imgThresholded);
// 轮廓最小外接矩形的绘制 和 粗略计算物体像素长宽
OpenCvSharp.Point[][] contours;
HierarchyIndex[] hierarchies;
// 1.2查找轮廓
Cv2.FindContours(imgThresholded, out contours, out hierarchies, RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
//排序
//SortContourPoint(contours, contours, 0, true);
//1.3绘制所有轮廓
dst = src_img.Clone();
Cv2.DrawContours(dst, contours, -1, new Scalar(0, 0, 255), 1, LineTypes.Link8, hierarchies);
//2.由轮廓确定正外接矩形及最小外接矩形
//2.1 定义Rect类型的vector容器boundRect存放正外接矩形,初始化大小为contours.Length)即轮廓个数
Rect[] boundRect = new Rect[contours.Length];
//2.2 定义Rect类型的vector容器roRect存放最小外接矩形,初始化大小为contours.Length)即轮廓个数
RotatedRect[] roRect = new RotatedRect[contours.Length];
//2.3 遍历每个轮廓
for (int i = 0; i < contours.Length; i++)
{
//2.4 由轮廓(点集)确定出正外接矩形并绘制
boundRect[i] = Cv2.BoundingRect(contours[i]);
//2.4.1获得正外接矩形的左上角坐标及宽高
int width = boundRect[i].Width;
int height = boundRect[i].Height;
int x = boundRect[i].X;
int y = boundRect[i].Y;
//2.4.2用画矩形方法绘制正外接矩形
Cv2.Rectangle(dst, boundRect[i], new Scalar(255, 0, 0), 2, LineTypes.Link8, 0);
//2.5 由轮廓(点集)确定出最小外接矩形并绘制
//旋转矩形主要成员有center、size、 angle、points()
roRect[i] = Cv2.MinAreaRect(contours[i]);
//2.5.1 旋转矩形类RotatedRect中有Point()方法,参数Point2f* pts,将旋转矩形的四个端点存储进pts.
Point2f[] pts = roRect[i].Points(); //把最小外接矩形四个端点复制给pts数组
//2.5.2 用line方法,根据旋转矩形的四个角点画出最小外接矩形每条边
for (int j = 0; j < 4; j++)
{
Cv2.Line(dst,(int)pts[j].X, (int)pts[j].Y, (int)pts[(j+1)%4].X, (int)pts[(j + 1) % 4].Y, new Scalar(0, 0, 255), 2, LineTypes.Link8, 0);
}
//*2.5.3 由旋转矩形的center成员得出中心点
Point2f center = roRect[i].Center;
//*2.5.4 用circle方法画出中心点center
Cv2.Circle(dst,(int) center.X, (int)center.Y, 5, new Scalar(0, 255, 0), -1, LineTypes.Link8,0);
//*2.5.5 由旋转矩形的size成员得出宽和高
double widthRotated = roRect[i].Size.Width;
double heightRotated = roRect[i].Size.Height;
Cv2.PutText(dst, "W:" + widthRotated.ToString(""), new OpenCvSharp.Point(20 , 40 + i * 100), HersheyFonts.HersheySimplex, 1, new Scalar(255, 0, 0), 1, LineTypes.Link8);
Cv2.PutText(dst, "H:" + heightRotated.ToString(""), new OpenCvSharp.Point(20, 60 + i * 100), HersheyFonts.HersheySimplex, 1, new Scalar(255, 0, 0), 1, LineTypes.Link8);
Cv2.PutText(dst, "NO:" + i.ToString(""), new OpenCvSharp.Point(20, 20+ i * 100), HersheyFonts.HersheySimplex, 1, new Scalar(255, 0, 0), 1, LineTypes.Link8);
}
Cv2.ImShow("粗略计算物体像素长宽", dst);
}
}
四、运行结果
![](https://img.haomeiwen.com/i17748967/02749fbc66843c2b.png)
五、资料
c1learning的博客:
https://blog.csdn.net/c1learning/article/details/100130805
网友评论