C#调用OpenCvSharp计算并显示带掩膜的图像直方图

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

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是C#窗体OpenCvSharp绘制图像轮廓与凸包、图像修补、绘制直方图直方图对比的示例代码: ```csharp using System; using System.Drawing; using System.Linq; using System.Windows.Forms; using OpenCvSharp; using OpenCvSharp.Extensions; namespace OpenCvSharpDemo { public partial class MainForm : Form { private readonly Mat _srcImage; private Mat _grayImage; private Mat _binaryImage; public MainForm() { InitializeComponent(); // 加载图像 _srcImage = Cv2.ImRead("test.jpg"); // 显示原图 pictureBox1.Image = BitmapConverter.ToBitmap(_srcImage); } private void button1_Click(object sender, EventArgs e) { // 转化为灰度图像 _grayImage = _srcImage.CvtColor(ColorConversionCodes.BGR2GRAY); // 显示灰度图像 pictureBox1.Image = BitmapConverter.ToBitmap(_grayImage); } private void button2_Click(object sender, EventArgs e) { // 二值化图像 _binaryImage = _grayImage.Threshold(0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu); // 显示二值化图像 pictureBox1.Image = BitmapConverter.ToBitmap(_binaryImage); } private void button3_Click(object sender, EventArgs e) { // 查找轮廓 var contours = _binaryImage.FindContoursAsArray(RetrievalModes.External, ContourApproximationModes.ApproxSimple); // 绘制轮廓 var dstImage = _srcImage.Clone(); dstImage.DrawContours(contours, -1, Scalar.Red, 2); // 显示绘制后的图像 pictureBox1.Image = BitmapConverter.ToBitmap(dstImage); } private void button4_Click(object sender, EventArgs e) { // 查找轮廓 var contours = _binaryImage.FindContoursAsArray(RetrievalModes.External, ContourApproximationModes.ApproxSimple); // 查找凸包 var hulls = contours.Select(c => Cv2.ConvexHull(c)).ToList(); // 绘制凸包 var dstImage = _srcImage.Clone(); for (var i = 0; i < contours.Length; i++) { dstImage.DrawContours(new[] { hulls[i] }, -1, Scalar.Green, 2); } // 显示绘制后的图像 pictureBox1.Image = BitmapConverter.ToBitmap(dstImage); } private void button5_Click(object sender, EventArgs e) { // 查找轮廓 var contours = _binaryImage.FindContoursAsArray(RetrievalModes.External, ContourApproximationModes.ApproxSimple); // 查找最大轮廓 var maxContour = contours.OrderByDescending(c => c.ContourArea()).First(); // 创建掩膜图像 var mask = new Mat(_binaryImage.Size(), MatType.CV_8UC1, Scalar.White); mask.DrawContours(new[] { maxContour }, -1, Scalar.Black, -1); // 修补图像 var dstImage = _srcImage.Clone(); Cv2.Inpaint(dstImage, mask, dstImage, 3, InpaintMethod.Telea); // 显示修补后的图像 pictureBox1.Image = BitmapConverter.ToBitmap(dstImage); } private void button6_Click(object sender, EventArgs e) { // 计算直方图 var hist = new Mat(); Cv2.CalcHist(new[] { _srcImage }, new[] { 0 }, null, hist, 1, new[] { 256 }, new[] { new[] { 0, 256 } }); // 绘制直方图 var histImage = new Mat(new Size(512, 400), MatType.CV_8UC3, Scalar.White); Cv2.Normalize(hist, hist, 0, histImage.Rows, NormTypes.MinMax); var binWidth = (int)(histImage.Cols / 256.0); for (var i = 1; i < 256; i++) { var x1 = (i - 1) * binWidth; var y1 = histImage.Rows - (int)hist.Get<float>(i - 1); var x2 = i * binWidth; var y2 = histImage.Rows - (int)hist.Get<float>(i); histImage.Line(new Point(x1, y1), new Point(x2, y2), Scalar.Black, 2); } // 显示绘制后的直方图 pictureBox1.Image = BitmapConverter.ToBitmap(histImage); } private void button7_Click(object sender, EventArgs e) { // 加载对比图像 var dstImage = Cv2.ImRead("test2.jpg"); // 计算对比直方图 var srcHist = new Mat(); Cv2.CalcHist(new[] { _srcImage }, new[] { 0 }, null, srcHist, 1, new[] { 256 }, new[] { new[] { 0, 256 } }); var dstHist = new Mat(); Cv2.CalcHist(new[] { dstImage }, new[] { 0 }, null, dstHist, 1, new[] { 256 }, new[] { new[] { 0, 256 } }); // 计算直方图相似度 var similarity = Cv2.CompareHist(srcHist, dstHist, HistCompMethods.Correl); // 显示相似度 MessageBox.Show($"相似度:{similarity:F2}"); } } } ``` 其中,各个按钮的功能如下: - “灰度化”按钮:将原图像转化为灰度图像显示; - “二值化”按钮:将灰度图像转化为二值图像显示; - “绘制轮廓”按钮:在原图像上绘制轮廓并显示; - “绘制凸包”按钮:在原图像上绘制轮廓的凸包并显示; - “图像修补”按钮:对原图像进行修补并显示; - “绘制直方图”按钮:计算图像直方图并绘制并显示; - “直方图对比”按钮:计算图像与对比图像直方图相似度并显示。 注释已经在代码中添加,希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值