C# OpenCvSharp 直方图均衡化 图像去雾

目录

效果

直方图

直方图均衡化

自适应的直方图均衡化

全局直方图均衡化

局部直方图均衡化

对比度调整

项目

代码


效果

直方图

图片

直方图均衡化

图片

自适应的直方图均衡化

图片

全局直方图均衡化

图片

局部直方图均衡化

图片

对比度调整

图片

项目

图片

代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OpenCvSharp;
 
namespace OpenCvSharp_图像去雾
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string imgPath = "";
 
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;
            pictureBox1.Image = null;
            imgPath = ofd.FileName;
            pictureBox1.Image = new Bitmap(imgPath);
        }
 
        /// <summary>
        /// 直方图均衡化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if (imgPath == "") return;
            Mat mat = Cv2.ImRead(imgPath, ImreadModes.Grayscale);
            Cv2.EqualizeHist(mat, mat);
            pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
        }
 
        /// <summary>
        /// 自适应的直方图均衡化
        /// 将整幅图像分成很多小块,然后再对每一个小块分别进行直方图均衡化,最后进行拼接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            if (imgPath == "") return;
            Mat mat = Cv2.ImRead(imgPath, ImreadModes.Grayscale);
            CLAHE clahe = Cv2.CreateCLAHE(10.0, new OpenCvSharp.Size(8, 8));
            clahe.Apply(mat, mat);
            pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
        }
 
        /// <summary>
        /// 全局直方图处理
        /// 全局直方图处理通过对 RGB 图像的 R、G、B 三层通道分别进行直方图均衡化,再整合到新的图像的方式进行。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            if (imgPath == "") return;
            Mat mat = Cv2.ImRead(imgPath);
            Mat[] mats = Cv2.Split(mat);//拆分
            //Mat mats0 =  mats[0];//B
            //Mat mats1 =  mats[1];//G
            //Mat mats2 =  mats[2];//R
 
            Cv2.EqualizeHist(mats[0], mats[0]);
            Cv2.EqualizeHist(mats[1], mats[1]);
            Cv2.EqualizeHist(mats[2], mats[2]);
 
            Cv2.Merge(new Mat[] { mats[0], mats[1], mats[2] }, mat);
 
            pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
        }
 
        /// <summary>
        ///  局部直方图处理
        ///  即自适应直方图均衡化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            if (imgPath == "") return;
            CLAHE clahe = Cv2.CreateCLAHE(6.0, new OpenCvSharp.Size(8, 8));
            Mat mat = Cv2.ImRead(imgPath);
            Mat[] mats = Cv2.Split(mat);//拆分
            clahe.Apply(mats[0], mats[0]);//B
            clahe.Apply(mats[1], mats[1]);//G
            clahe.Apply(mats[2], mats[2]);//R
 
            Cv2.Merge(new Mat[] { mats[0], mats[1], mats[2] }, mat);
 
            pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
        }
 
        /// <summary>
        /// 直方图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, EventArgs e)
        {
            if (imgPath == "") return;
            Mat lena = Cv2.ImRead(imgPath);
            Mat[] mats = Cv2.Split(lena);//一张图片,将lena拆分成3个图片装进mat
            Mat[] mats0 = new Mat[] { mats[0] };//B
            Mat[] mats1 = new Mat[] { mats[1] };//G
            Mat[] mats2 = new Mat[] { mats[2] };//R
            Mat[] hist = new Mat[] { new Mat(), new Mat(), new Mat() };//一个矩阵数组,用来接收直方图,记得全部初始化
            int[] channels = new int[] { 0 };//一个通道,初始化为通道0
            int[] histsize = new int[] { 256 };//初始化为256箱子
            Rangef[] range = new Rangef[1];//一个通道,范围
            range[0] = new Rangef(0, 256);//从0开始(含),到256结束(不含)
            Mat mask = new Mat();//不做掩码
            Cv2.CalcHist(mats0, channels, mask, hist[0], 1, histsize, range);//对被拆分的图片单独进行计算
            Cv2.CalcHist(mats1, channels, mask, hist[1], 1, histsize, range);//对被拆分的图片单独进行计算
            Cv2.CalcHist(mats2, channels, mask, hist[2], 1, histsize, range);//对被拆分的图片单独进行计算
            Cv2.Normalize(hist[0], hist[0], 0, 256, NormTypes.MinMax);// 归一化
            Cv2.Normalize(hist[1], hist[1], 0, 256, NormTypes.MinMax);// 归一化
            Cv2.Normalize(hist[2], hist[2], 0, 256, NormTypes.MinMax);// 归一化
 
            double minVal0, maxVal0;
            Cv2.MinMaxLoc(hist[0], out minVal0, out maxVal0);
            double minVal1, maxVal1;
            Cv2.MinMaxLoc(hist[1], out minVal1, out maxVal1);
            double minVal2, maxVal2;
            Cv2.MinMaxLoc(hist[2], out minVal2, out maxVal2);
 
            double minVal = Math.Min(minVal0, Math.Min(minVal1, minVal2));
            double maxVal = Math.Max(maxVal0, Math.Max(maxVal1, maxVal2));
 
            int height = 512;
            int width = 512;
 
            hist[0] = hist[0] * (maxVal != 0 ? height / maxVal : 0.0);
            hist[1] = hist[1] * (maxVal != 0 ? height / maxVal : 0.0);
            hist[2] = hist[2] * (maxVal != 0 ? height / maxVal : 0.0);
 
            Mat histImage = new Mat(height, width, MatType.CV_8UC3, new Scalar(100, 100, 100));
            int binW = (int)((double)width / histsize[0]);
            for (int i = 0; i < histsize[0]; i++)
            {
                histImage.Rectangle(
                                    new OpenCvSharp.Point(i * binW, histImage.Rows - (int)hist[0].Get<float>(i)),
                                    new OpenCvSharp.Point((i + 1) * binW, histImage.Rows),
                                     new Scalar(255, 0, 0),
                                    -1);
 
                histImage.Rectangle(
                    new OpenCvSharp.Point(i * binW, histImage.Rows - (int)hist[1].Get<float>(i)),
                    new OpenCvSharp.Point((i + 1) * binW, histImage.Rows),
                     new Scalar(0, 255, 0),
                    -1);
 
                histImage.Rectangle(
                    new OpenCvSharp.Point(i * binW, histImage.Rows - (int)hist[2].Get<float>(i)),
                    new OpenCvSharp.Point((i + 1) * binW, histImage.Rows),
                     new Scalar(0, 0, 255),
                    -1);
            }
            pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImage);
            //Cv2.ImShow("hist", histImage);
        }
 
        /// <summary>
        /// 画面对比度调整
        /// 此处需要注意的是采用了YCrCB格式,该格式的Y通道是亮度,对其调整,实际上调整的是对比度,不会导致图片本身的失真。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            if (imgPath == "") return;
            Mat lena = Cv2.ImRead(imgPath, ImreadModes.Color);
            Mat yCbCR = new Mat();
            Cv2.CvtColor(lena, yCbCR, ColorConversionCodes.BGR2YCrCb);
            Mat[] channels = Cv2.Split(yCbCR);//一张图片,将lena拆分成3个图片装进mat
            Cv2.EqualizeHist(channels[0], channels[0]);
            Cv2.Merge(channels, yCbCR);
            Mat result = new Mat();
            Cv2.CvtColor(yCbCR, result, ColorConversionCodes.YCrCb2BGR);
            pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(result);
            //Cv2.ImShow("origin", lena);
            //Cv2.ImShow("EqualizeHist", result);
        }
    }
}

 引入地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值