之前的文章简要测试了调用OpenCvSharp的Cv2.CalcHist函数计算直方图的用法,不过使用过程中参数mask的值始终为null,也就是计算的整幅图像的直方图,如果mask不为空,则可以计算图像指定区域的直方图,本文学习掩膜的创建方式并调用CalcHist计算并绘制带掩膜的图像直方图。
public static void CalcHist(Mat[] images, int[] channels, InputArray? mask, OutputArray hist, int dims, int[] histSize, Rangef[] ranges, bool uniform = true, bool accumulate = false)
首先加载图像并将其转换为灰度图,然后计算并显示整幅图像的图像直方图。
oriImage = Cv2.ImRead(ofd.FileName);
grayImage = new Mat();
Cv2.CvtColor(oriImage, grayImage, ColorConversionCodes.BGR2GRAY);image = grayImage.ToBitmap();
picImage.Refresh();OpenCvSharp.Rangef range = new OpenCvSharp.Rangef(0, 256);
Mat outputArray = new Mat();
Cv2.CalcHist(new Mat[] { grayImage }, new int[] { 0 }, null, outputArray, 1, new int[] { 256 }, new OpenCvSharp.Rangef[] { range });
Cv2.Normalize(outputArray, outputArray, 0, outputArray.Rows, NormTypes.MinMax, -1);mat = outputArray;
skControl1.Refresh();
设置PictureBox控件的MouseDown、MouseMove、MouseUp事件响应函数,用于选中灰度图中的部分区域,并将选中区域转换为掩膜数据。计算并绘制带掩膜的图像直方图,同时调用Cv2.BitwiseAnd函数计算掩膜区域图像。主要代码如下所示:
private bool m_beginSelect = false;private Rectangle m_selectRect;private System.Drawing.Point m_startPoint;private Mat m_mask;private void picImage_MouseDown(object sender, MouseEventArgs e){m_beginSelect = true;m_startPoint = e.Location;}
private void picImage_MouseMove(object sender, MouseEventArgs e){if (m_beginSelect){m_selectRect.X = Math.Min(e.X, m_startPoint.X);m_selectRect.Y = Math.Min(e.Y, m_startPoint.Y);m_selectRect.Width = Math.Abs(e.X - m_startPoint.X);m_selectRect.Height = Math.Abs(e.Y - m_startPoint.Y);picImage.Refresh();}}private void picImage_MouseUp(object sender, MouseEventArgs e){if (m_beginSelect){......//创建掩膜对象Mat mask = new Mat(grayImage.Size(), MatType.CV_8UC1, Scalar.All(0));Rect roi = new Rect(m_selectRect.X, m_selectRect.Y, m_selectRect.Width,m_selectRect.Height);mask[roi].SetTo(new Scalar(255));//计算带掩膜的图像直方图OpenCvSharp.Rangef range = new OpenCvSharp.Rangef(0, 256);Mat outputArray = new Mat();Cv2.CalcHist(new Mat[] { grayImage }, new int[] { 0 }, mask, outputArray, 1, new int[] { 256 }, new OpenCvSharp.Rangef[] { range });Cv2.Normalize(outputArray, outputArray, 0, outputArray.Rows, NormTypes.MinMax, -1);matMask = outputArray;skControl2.Refresh();//计算并显示掩膜区域图像Mat masked_img = new Mat();Cv2.BitwiseAnd(grayImage, grayImage, masked_img, mask);Cv2.ImShow("掩码图片", masked_img);}m_beginSelect = false;}
下图是程序运行效果。
参考文献:
[1]https://www.bilibili.com/video/BV1DT421m7S8?p=13&spm_id_from=pageDriver&vd_source=db4a1f65c18549c78df3e9d579e59e19
[2]https://blog.csdn.net/m0_55074196/article/details/132064485
[3]https://download.csdn.net/blog/column/11613741/123986941