c# openCV扬尘识别
分水岭算法是关键
·
private void yangchen_Click(object sender, EventArgs e)
{
var fileName = string.Empty;
OpenFileDialog openDlg = new OpenFileDialog();
if (openDlg.ShowDialog() == DialogResult.OK)
{
fileName = openDlg.FileName;
}
Mat g_midimage = new Mat();
Mat himg = new Mat();
Mat simg = new Mat();
Mat vimg = new Mat();
Mat tmpimage = new Mat();
Mat binary_image = new Mat();
Mat g_srcimage = Cv2.ImRead(fileName);//读图片
Cv2.CvtColor(g_srcimage, g_midimage, ColorConversionCodes.BGR2HSV);//RGB转HSV
Mat[] mats = Cv2.Split(g_midimage);//分离HSV三通道,分成三张图片
himg = mats[0];
simg = mats[1];
vimg = mats[2];
#region 二值化H,S,V图像
for (int i = 0; i < himg.Rows; i++)
{
for (int j = 0; j < himg.Cols; j++)
{
byte hvalue = himg.At<byte>(i, j);
if ((hvalue > 0 && hvalue < 30) || (hvalue > 170 && hvalue < 180))//当H图像像素值在0~30和170~180范围内时,得到为白色否则为黑,下面相同。
himg.At<byte>(i, j) = 255;
else
himg.At<byte>(i, j) = 0;
}
}
for (int i = 0; i < simg.Rows; i++)
{
for (int j = 0; j < simg.Cols; j++)
{
byte svalue = simg.At<byte>(i, j);
if ((svalue > 0 && svalue < 20) || (svalue > 50 && svalue < 100))
simg.At<byte>(i, j) = 255;
else
simg.At<byte>(i, j) = 0;
}
}
for (int i = 0; i < vimg.Rows; i++)
{
for (int j = 0; j < vimg.Cols; j++)
{
byte vvalue = vimg.At<byte>(i, j);
if (vvalue > 170 && vvalue < 220)
vimg.At<byte>(i, j) = 255;
else
vimg.At<byte>(i, j) = 0;
}
}
#endregion
//将三通道合并,最终得到二值化图像binary_image
Cv2.BitwiseAnd(himg, simg, tmpimage);
Cv2.BitwiseAnd(tmpimage, vimg, binary_image);
//Cv2.ImShow("binary", binary_image);
//腐蚀操作得到前景图片,腐蚀6次
Mat fg = new Mat();
Cv2.Erode(binary_image, fg, new Mat(), new Point(-1, -1), 6);
//显示前景图片
//Cv2.ImShow("foreground", fg);
//膨胀操作,膨胀6次
Mat bg = new Mat(); ;
Cv2.Dilate(binary_image, bg, new Mat(), new Point(-1, -1), 6);
//将膨胀的图片阈值化操作,得到背景图片,
var Scalarscalar = Cv2.Mean(g_midimage);//计算灰度图平均值
Cv2.Threshold(bg, bg, Scalarscalar.Val2, 128, ThresholdTypes.BinaryInv);
//显示背景图片
//Cv2.ImShow("background", bg);
//将前景和背景图片相加,得到掩膜图片
//Mat markers(binary_image.size(), CV_8U, Scalar(0));
Mat markers = new Mat(binary_image.Size(), MatType.CV_8U, new Scalar(0));
markers = fg + bg;
//Cv2.ImShow("markers", markers);
//分水岭函数的掩膜必须是32位的,故将八位图片转化成32位图片,进行分水岭操作,结果存在markers中
markers.ConvertTo(markers, MatType.CV_32S);
Cv2.Watershed(g_srcimage, markers);
//将得到的markers图片转化成八位图片
Mat tmp = new Mat();
markers.ConvertTo(tmp, MatType.CV_8U);
//像素统计,逐行统计,计算白色区域的像素和
double pixekcount = 0.0, blackcount = 0.0;
for (int i = 0; i < tmp.Rows; i++)
{
for (int j = 0; j < tmp.Cols; j++)
{
pixekcount++;
byte gvalue = tmp.At<byte>(i, j);
if (gvalue == 255)
blackcount++;
}
}
//计算白色区域的比例
double scale_img;
scale_img = blackcount / pixekcount;
//大于0.05则在图上打上有问题的标签
if (scale_img > 0.05)
{
Cv2.PutText(tmp, "have question", new Point(0, 10), HersheyFonts.HersheyComplex, 0.3, new Scalar(255, 0, 0));//打印函数
Cv2.ImShow("segment", tmp);//显示有问题的图片,按计划这里应该是传图片或者存图片
//MessageBox.Show("have question");
}
else
{
}
//Cv2.ImShow("segment", tmp);//显示最终的图片
Cv2.WaitKey(0);
}
更多推荐
所有评论(0)