概要:
本篇文章主要分享基于OpenCvSharp库,使用SVM(想要详细了解什么是SVM点这里SVM简解,还有详解:SVM详解,OpenCv中SVM参数详解:官方入口)进行目标物体的识别与分类;案例中识别的随机撒放的螺丝、螺母、垫片、方片,三角扣并且标签分类;
原图如下所示:
处理结果:
主要处理步骤:
- 图像预处理
- 特征提取
- 模型训练
- 识别分类
详细流程:
图像预处理。
- 图像降噪,背景消除,代码中使用的时盒子滤波去噪(BoxFilter)。由于拍摄环境相对理想,所以处理起来不复杂,模糊图像获得背景图片,原图与背景图做差,达到背景去除的目的。然后图像二值化,便于后续处理。
下图所示:
代码如下:
public Mat CalculateLightPattern(Mat mat)
{
Mat pattern = new Mat();
Cv2.Blur(mat, pattern, new Size(mat.Cols, mat.Width));
return pattern;
}
public Mat RemoveBgm(Mat img, Mat pattern)
{
Mat result = new Mat();
Mat img32 = new Mat();
Mat pattern32 = new Mat();
img.ConvertTo(img32, MatType.CV_32F);
pattern.ConvertTo(pattern32, MatType.CV_32F);
result = 1 - (pattern32 / img32);
result = result * 255;
result.ConvertTo(result, MatType.CV_8U);
return result;
}
public Mat PreProcessImg(Mat input)
{
Cv2.CvtColor(input, input, ColorConversionCodes.BGR2GRAY);
Mat result = new Mat();
Mat imgNoise = new Mat();
imgNoise = BoxFilter(input, MatType.CV_8UC3, new Size(3, 3)); //MedBlurImage(input);//
//remove background
Mat imgNoLight = new Mat();
Mat lightPattern = CalculateLightPattern(imgNoise);
imgNoLight = RemoveBgm(imgNoise, lightPattern);
//Cv2.ImShow("imgNoLight", imgNoLight);
//Cv2.WaitKey(0);
Cv2.Threshold(imgNoLight, result, 200, 255, ThresholdTypes.Binary);
//Mat morphImg = MorphImage(result, MorphShapes.Rect, MorphTypes.Open, 2, new OpenCvSharp.Size(3, 3));
//Cv2.WaitKey(0);
//Rect rect = new Rect(100, 100, 500, 400);
//Mat mat = new Mat(result, rect);
//Cv2.ImShow(DateTime.Now.ToString("yyyyMMddHHmmssfff") + "morphImg", mat);
return result;
}
- 目标提取,代码中使用OpenCvSharp中ConnectedComponentsWithStats方法,将处理好的二值图像进行像素连接,标记目标。若邻接像素有相同值,则连接起来。从而获得目标图像形状。
处理结果下图所示:
代码如下:
/// <summary>
/// 初步目标检测
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public int TargetDectation(string path)
{
//读取图像
Mat imageRGB = Cv2.ImRead(path, ImreadModes.AnyColor);
Mat imageGray = new Mat();
if (imageRGB.Empty())
{
return -1;
}
Cv2.CvtColor(imageRGB, imageGray, ColorConversionCodes.RGB2GRAY);
Cv2.ImShow("Gray", imageGray);
//降噪
Mat blur = BoxFilter(imageGray, MatType.CV_8UC3, new Size(5, 5));//5,5 ,0,0
//获取背景
Mat imgPattern = CalculateLightPattern(blur);
//移除背景
Mat newGray = RemoveBgm(blur, imgPattern);
Cv2.ImShow("newGray", newGray);
//阈值化
Mat imageThr = new Mat();
Cv2.Threshold(newGray, imageThr, 50, 255, ThresholdTypes.Binary);
Cv2.ImShow("thr", imageThr);
//通过连通组件算法分割
imageThr = MorphImage(imageThr, MorphShapes.Ellipse, MorphTypes.Open, 2, new Size(3, 3));
Mat labels = new Mat();
Mat stats = new Mat();
Mat centroids = new Mat();
/*
以下是大概的代码,其中值得注意的是ConnectedComponentsWithStats函数的三个参数labelMat, stats, centroids。
1、在python、c++版本的opencv里面和OpencvSharp的使用有所区别,OpencvSharp返回的是Mat。
2、OpencvSharp版本里面centroids是2列若干行的矩阵,是64FC1所以取值形式centroids.At<double>(h, 0)ÿ