之前的文章简要测试了调用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