OpenCvSharp Demo 饱和度、明度、对比度、锐化、阴影、高光、色温实现滤镜效果

目录

效果

风景-天空滤镜

人像—酷感冷艳滤镜

美食—鲜美滤镜

美食—巧克力滤镜

项目

代码

参考 

下载


效果

风景-天空滤镜

人像—酷感冷艳滤镜

美食—鲜美滤镜

美食—巧克力滤镜

项目

代码

using OpenCvSharp;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Security.Cryptography;
using System.Windows.Forms;

namespace OpenCvSharp_Demo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string startupPath;
        string image_path;

        Stopwatch stopwatch = new Stopwatch();

        Mat image;
        Mat result_image;

        private void Form1_Load(object sender, EventArgs e)
        {
            startupPath = System.Windows.Forms.Application.StartupPath;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;
            pictureBox2.Image = null;
            textBox1.Text = "";

            image_path = ofd.FileName;
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);
        }

        byte max2(byte a, byte b)
        {
            return a > b ? a : b;
        }

        byte min2(byte a, byte b)
        {
            return a < b ? a : b;
        }

        byte max3(byte a, byte b, byte c)
        {
            return a > b ? max2(a, c) : max2(b, c);
        }

        byte min3(byte a, byte b, byte c)
        {
            return a < b ? min2(a, c) : min2(b, c);
        }

        /// <summary>
        /// 饱和度
        /// </summary>
        /// <param name="src"></param>
        /// <param name="percent"></param>
        /// <returns></returns>
        unsafe Mat Saturation(Mat src, int percent)
        {
            float Increment = percent * 1.0f / 100;
            Mat temp = src.Clone();
            int row = src.Rows;
            int col = src.Cols;
            for (int i = 0; i < row; ++i)
            {
                byte* t = (byte*)temp.Ptr(i);
                byte* s = (byte*)src.Ptr(i);
                for (int j = 0; j < col; ++j)
                {
                    byte b = s[3 * j];
                    byte g = s[3 * j + 1];
                    byte r = s[3 * j + 2];
                    float max = max3(r, g, b);
                    float min = min3(r, g, b);
                    float delta, value;
                    float L, S, alpha;
                    delta = (max - min) / 255;
                    if (delta == 0)
                        continue;
                    value = (max + min) / 255;
                    L = value / 2;
                    if (L < 0.5)
                        S = delta / value;
                    else
                        S = delta / (2 - value);
                    if (Increment >= 0)
                    {
                        if ((Increment + S) >= 1)
                            alpha = S;
                        else
                            alpha = 1 - Increment;
                        alpha = 1 / alpha - 1;
                        t[3 * j + 2] = (byte)(r + (r - L * 255) * alpha);
                        t[3 * j + 1] = (byte)(g + (g - L * 255) * alpha);
                        t[3 * j] = (byte)(b + (b - L * 255) * alpha);
                    }
                    else
                    {
                        alpha = Increment;
                        t[3 * j + 2] = (byte)(L * 255 + (r - L * 255) * (1 + alpha));
                        t[3 * j + 1] = (byte)(L * 255 + (g - L * 255) * (1 + alpha));
                        t[3 * j] = (byte)(L * 255 + (b - L * 255) * (1 + alpha));
                    }
                }
            }
            return temp;
        }

        /// <summary>
        /// 明度
        /// </summary>
        /// <param name="src"></param>
        /// <param name="percent"></param>
        /// <returns></returns>
        unsafe Mat Lightness(Mat src, float percent)
        {
            float alpha = percent / 100;
            alpha = Math.Max(-1.0f, Math.Min(1.0f, alpha));
            Mat temp = src.Clone();
            int row = src.Rows;
            int col = src.Cols;
            for (int i = 0; i < row; ++i)
            {

                byte* t = (byte*)temp.Ptr(i);
                byte* s = (byte*)src.Ptr(i);

                for (int j = 0; j < col; ++j)
                {
                    byte b = s[3 * j];
                    byte g = s[3 * j + 1];
                    byte r = s[3 * j + 2];
                    if (alpha >= 0)
                    {
                        t[3 * j + 2] = (byte)(r * (1 - alpha) + 255 * alpha);
                        t[3 * j + 1] = (byte)(g * (1 - alpha) + 255 * alpha);
                        t[3 * j] = (byte)(b * (1 - alpha) + 255 * alpha);
                    }
                    else
                    {
                        t[3 * j + 2] = (byte)(r * (1 + alpha));
                        t[3 * j + 1] = (byte)(g * (1 + alpha));
                        t[3 * j] = (byte)(b * (1 + alpha));
                    }
                }
            }
            return temp;
        }

        /// <summary>
        /// 对比度
        /// </summary>
        unsafe Mat Contrast(Mat src, int percent)
        {
            float alpha = percent / 100.0f;
            alpha = Math.Max(-1.0f, Math.Min(1.0f, alpha));
            Mat temp = src.Clone();
            int row = src.Rows;
            int col = src.Cols;
            int thresh = 127;
            for (int i = 0; i < row; ++i)
            {
                byte* t = (byte*)temp.Ptr(i);
                byte* s = (byte*)src.Ptr(i);
                for (int j = 0; j < col; ++j)
                {
                    byte b = s[3 * j];
                    byte g = s[3 * j + 1];
                    byte r = s[3 * j + 2];
                    int newb, newg, newr;
                    if (alpha == 1)
                    {
                        t[3 * j + 2] = (byte)(r > thresh ? 255 : 0);
                        t[3 * j + 1] = (byte)(g > thresh ? 255 : 0);
                        t[3 * j] = (byte)(b > thresh ? 255 : 0);
                        continue;
                    }
                    else if (alpha >= 0)
                    {
                        newr = (int)(thresh + (r - thresh) / (1 - alpha));
                        newg = (int)(thresh + (g - thresh) / (1 - alpha));
                        newb = (int)(thresh + (b - thresh) / (1 - alpha));
                    }
                    else
                    {
                        newr = (int)(thresh + (r - thresh) * (1 + alpha));
                        newg = (int)(thresh + (g - thresh) * (1 + alpha));
                        newb = (int)(thresh + (b - thresh) * (1 + alpha));

                    }
                    newr = Math.Max(0, Math.Min(255, newr));
                    newg = Math.Max(0, Math.Min(255, newg));
                    newb = Math.Max(0, Math.Min(255, newb));
                    t[3 * j + 2] = (byte)(newr);
                    t[3 * j + 1] = (byte)(newg);
                    t[3 * j] = (byte)(newb);
                }
            }
            return temp;
        }

        /// <summary>
        /// 图像阴影选取
        /// </summary>
        /// <param name="input"></param>
        /// <param name="light"></param>
        /// <returns></returns>
        unsafe Mat Shadow(Mat input, int light)
        {
            // 生成灰度图
            Mat gray = Mat.Zeros(input.Size(), MatType.CV_32FC1);
            Mat f = input.Clone();
            f.ConvertTo(f, MatType.CV_32FC3);
            Mat[] pics = new Mat[3] { new Mat(), new Mat(), new Mat() };
            Cv2.Split(f, out pics);
            gray = 0.299f * pics[2] + 0.587 * pics[1] + 0.114 * pics[0];
            gray = gray / 255.0f;

            // 确定阴影区
            Mat thresh = Mat.Zeros(gray.Size(), gray.Type());
            thresh = (1.0f - gray).Mul(1.0f - gray);

            // 取平均值作为阈值
            Scalar t = Cv2.Mean(thresh);
            Mat mask = Mat.Zeros(gray.Size(), MatType.CV_8UC1);
            mask.SetTo(new Scalar(255), thresh.GreaterThanOrEqual(t.Val0));


            // 参数设置
            int max = 4;
            float bright = light / 100.0f / max;
            float mid = 1.0f + max * bright;

            // 边缘平滑过渡
            Mat midrate = Mat.Zeros(input.Size(), MatType.CV_32FC1);
            Mat brightrate = Mat.Zeros(input.Size(), MatType.CV_32FC1);
            for (int i = 0; i < input.Rows; ++i)
            {
                byte* m = (byte*)mask.Ptr(i);
                float* th = (float*)thresh.Ptr(i);
                float* mi = (float*)midrate.Ptr(i);
                float* br = (float*)brightrate.Ptr(i);
                for (int j = 0; j < input.Cols; ++j)
                {
                    if (m[j] == 255)
                    {
                        mi[j] = mid;
                        br[j] = bright;
                    }
                    else
                    {
                        mi[j] = (float)((mid - 1.0f) / t[0] * th[j] + 1.0f);
                        br[j] = (float)((1.0f / t[0] * th[j]) * bright);
                    }
                }


            }

            // 阴影提亮,获取结果图
            Mat result = Mat.Zeros(input.Size(), input.Type());
            for (int i = 0; i < input.Rows; ++i)
            {
                float* mi = (float*)midrate.Ptr(i);
                float* br = (float*)brightrate.Ptr(i);
                byte* @in = (byte*)input.Ptr(i);
                byte* r = (byte*)result.Ptr(i);
                for (int j = 0; j < input.Cols; ++j)
                {
                    for (int k = 0; k < 3; ++k)
                    {
                        float temp = (float)(Math.Pow((float)(@in[3 * j + k]) / 255.0f, 1.0f / mi[j]) * (1.0 / (1 - br[j])));
                        if (temp > 1.0f)
                            temp = 1.0f;
                        if (temp < 0.0f)
                            temp = 0.0f;
                        byte utemp = (byte)(255 * temp);
                        r[3 * j + k] = utemp;
                    }

                }
            }
            return result;
        }

        /// <summary>
        /// 图像高光选取
        /// </summary>
        /// <param name="input"></param>
        /// <param name="light"></param>
        /// <returns></returns>
        unsafe Mat HighLight(Mat input, int light)
        {
            // 生成灰度图
            Mat gray = Mat.Zeros(input.Size(), MatType.CV_32FC1);
            Mat f = input.Clone();
            f.ConvertTo(f, MatType.CV_32FC3);
            Mat[] pics = new Mat[3] { new Mat(), new Mat(), new Mat() };
            Cv2.Split(f, out pics);
            gray = 0.299f * pics[2] + 0.587 * pics[1] + 0.114 * pics[0];
            gray = gray / 255.0f;

            // 确定高光区
            Mat thresh = Mat.Zeros(gray.Size(), gray.Type());
            thresh = gray.Mul(gray);
            // 取平均值作为阈值
            Scalar t = Cv2.Mean(thresh);
            Mat mask = Mat.Zeros(gray.Size(), MatType.CV_8UC1);
            mask.SetTo(new Scalar(255), thresh.GreaterThanOrEqual(t.Val0));

            // 参数设置
            int max = 4;
            float bright = light / 100.0f / max;
            float mid = 1.0f + max * bright;

            // 边缘平滑过渡
            Mat midrate = Mat.Zeros(input.Size(), MatType.CV_32FC1);
            Mat brightrate = Mat.Zeros(input.Size(), MatType.CV_32FC1);
            for (int i = 0; i < input.Rows; ++i)
            {

                byte* m = (byte*)mask.Ptr(i);
                float* th = (float*)thresh.Ptr(i);
                float* mi = (float*)midrate.Ptr(i);
                float* br = (float*)brightrate.Ptr(i);

                for (int j = 0; j < input.Cols; ++j)
                {
                    if (m[j] == 255)
                    {
                        mi[j] = mid;
                        br[j] = bright;
                    }
                    else
                    {
                        mi[j] = (float)((mid - 1.0f) / t[0] * th[j] + 1.0f);
                        br[j] = (float)((1.0f / t[0] * th[j]) * bright);
                    }
                }
            }

            // 高光提亮,获取结果图
            Mat result = Mat.Zeros(input.Size(), input.Type());
            for (int i = 0; i < input.Rows; ++i)
            {
                float* mi = (float*)midrate.Ptr(i);
                float* br = (float*)brightrate.Ptr(i);
                byte* @in = (byte*)input.Ptr(i);
                byte* r = (byte*)result.Ptr(i);


                for (int j = 0; j < input.Cols; ++j)
                {
                    for (int k = 0; k < 3; ++k)
                    {
                        float temp = (float)(Math.Pow((float)(@in[3 * j + k]) / 255.0f, 1.0f / mi[j]) * (1.0 / (1 - br[j])));
                        if (temp > 1.0f)
                            temp = 1.0f;
                        if (temp < 0.0f)
                            temp = 0.0f;
                        byte utemp = (byte)(255 * temp);
                        r[3 * j + k] = utemp;
                    }

                }
            }
            return result;
        }

        // 色温调节
        unsafe Mat ColorTemperature(Mat input, int n)
        {
            Mat result = input.Clone();
            int row = input.Rows;
            int col = input.Cols;
            int level = n / 2;
            for (int i = 0; i < row; ++i)
            {
                byte* a = (byte*)input.Ptr(i);
                byte* r = (byte*)result.Ptr(i);
                for (int j = 0; j < col; ++j)
                {
                    int R, G, B;
                    // R通道
                    R = a[j * 3 + 2];
                    R = R + level;
                    if (R > 255)
                    {
                        r[j * 3 + 2] = 255;
                    }
                    else if (R < 0)
                    {
                        r[j * 3 + 2] = 0;
                    }
                    else
                    {
                        r[j * 3 + 2] = (byte)R;
                    }
                    // G通道
                    G = a[j * 3 + 1];
                    G = G + level;
                    if (G > 255)
                    {
                        r[j * 3 + 1] = 255;
                    }
                    else if (G < 0)
                    {
                        r[j * 3 + 1] = 0;
                    }
                    else
                    {
                        r[j * 3 + 1] = (byte)G;
                    }
                    // B通道
                    B = a[j * 3];
                    B = B - level;
                    if (B > 255)
                    {
                        r[j * 3] = 255;
                    }
                    else if (B < 0)
                    {
                        r[j * 3] = 0;
                    }
                    else
                    {
                        r[j * 3] = (byte)B;
                    }
                }
            }
            return result;
        }

        // 图像锐化
        unsafe Mat Sharpen(Mat input, int percent, int type)
        {
            Mat result;
            Mat s = input.Clone();
            InputArray kernel;
            switch (type)
            {
                case 0:
                    kernel =
                    InputArray.Create<float>(new float[3, 3] {
                    { 0, -1, 0 },
                    { -1, 4, -1 },
                    { 0, -1, 0 } });
                    break;
                case 1:
                    kernel =
                    InputArray.Create<float>(new float[3, 3] {
                    {  -1, -1, -1},
                    {  -1, 8, -1 },
                    {  -1, -1, -1 } });

                    break;
                default:
                    kernel =
                    InputArray.Create<float>(new float[3, 3] {
                    {  0, -1, 0},
                    {  -1, 4, -1 },
                    {  0, -1, 0 } });

                    break;
            }
            Cv2.Filter2D(s, s, s.Depth(), kernel);
            result = input + s * 0.01 * percent;
            return result;
        }

        //天空滤镜
        private void button2_Click(object sender, EventArgs e)
        {
            stopwatch.Restart();

            image_path = "test_img\\sky.jpg";
            pictureBox1.Image = new Bitmap(image_path);

            Mat src = Cv2.ImRead(image_path);
            Mat sat = Saturation(src, 35);
            Mat lig = Lightness(sat, 20);
            Mat con = Contrast(lig, 15);
            Mat sdo = Shadow(con, 15);
            Mat hig = HighLight(sdo, -30);
            result_image = ColorTemperature(hig, -40);


            double costTime = stopwatch.Elapsed.TotalMilliseconds;
            textBox1.Text = $"耗时:{costTime:F2}ms";
            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (pictureBox2.Image == null)
            {
                return;
            }
            Bitmap output = new Bitmap(pictureBox2.Image);
            var sdf = new SaveFileDialog();
            sdf.Title = "保存";
            sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp|Images (*.emf)|*.emf|Images (*.exif)|*.exif|Images (*.gif)|*.gif|Images (*.ico)|*.ico|Images (*.tiff)|*.tiff|Images (*.wmf)|*.wmf";
            if (sdf.ShowDialog() == DialogResult.OK)
            {
                switch (sdf.FilterIndex)
                {
                    case 1:
                        {
                            output.Save(sdf.FileName, ImageFormat.Jpeg);
                            break;
                        }
                    case 2:
                        {
                            output.Save(sdf.FileName, ImageFormat.Png);
                            break;
                        }
                    case 3:
                        {
                            output.Save(sdf.FileName, ImageFormat.Bmp);
                            break;
                        }
                    case 4:
                        {
                            output.Save(sdf.FileName, ImageFormat.Emf);
                            break;
                        }
                    case 5:
                        {
                            output.Save(sdf.FileName, ImageFormat.Exif);
                            break;
                        }
                    case 6:
                        {
                            output.Save(sdf.FileName, ImageFormat.Gif);
                            break;
                        }
                    case 7:
                        {
                            output.Save(sdf.FileName, ImageFormat.Icon);
                            break;
                        }
                    case 8:
                        {
                            output.Save(sdf.FileName, ImageFormat.Tiff);
                            break;
                        }
                    case 9:
                        {
                            output.Save(sdf.FileName, ImageFormat.Wmf);
                            break;
                        }
                }
                MessageBox.Show("保存成功,位置:" + sdf.FileName);
            }
        }

        //人像—酷感冷艳滤镜
        private void button4_Click(object sender, EventArgs e)
        {
            stopwatch.Restart();

            image_path = "test_img\\test01.jpg";
            pictureBox1.Image = new Bitmap(image_path);

            Mat src = Cv2.ImRead(image_path);
            Mat con = Contrast(src, 25);
            Mat lig = Lightness(con, -30);
            Mat hig = HighLight(lig, 20);
            Mat sha = Sharpen(hig, 50, 0);
            Mat sat = Saturation(sha, 20);
            result_image = ColorTemperature(hig, -40);

            double costTime = stopwatch.Elapsed.TotalMilliseconds;
            textBox1.Text = $"耗时:{costTime:F2}ms";
            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());

        }

        //美食—鲜美滤镜
        private void button5_Click(object sender, EventArgs e)
        {

            stopwatch.Restart();

            image_path = "test_img\\test02.jpg";
            pictureBox1.Image = new Bitmap(image_path);

            Mat src = Cv2.ImRead(image_path);
            Mat sat = Saturation(src, 25);
            Mat lig = Lightness(sat, 10);
            Mat con = Contrast(lig, 30);
            Mat sha = Sharpen(con, 30, 0);
            Mat sdo = Shadow(sha, -5);
            result_image = HighLight(sdo, 15);

            double costTime = stopwatch.Elapsed.TotalMilliseconds;
            textBox1.Text = $"耗时:{costTime:F2}ms";
            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());


        }

        //美食—巧克力滤镜
        private void button6_Click(object sender, EventArgs e)
        {
            stopwatch.Restart();

            image_path = "test_img\\test03.jpg";
            pictureBox1.Image = new Bitmap(image_path);

            Mat src = Cv2.ImRead(image_path);
            Mat sat = Saturation(src, 20);
            Mat lig = Lightness(sat, -15);
            Mat con = Contrast(lig, 35);
            Mat sha = Sharpen(con, 10, 0);
            Mat sdo = Shadow(sha, 25);
            result_image = HighLight(sdo, -5);

            double costTime = stopwatch.Elapsed.TotalMilliseconds;
            textBox1.Text = $"耗时:{costTime:F2}ms";
            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
        }
    }
}
 

using OpenCvSharp;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Security.Cryptography;
using System.Windows.Forms;namespace OpenCvSharp_Demo
{public partial class Form1 : Form{public Form1(){InitializeComponent();}string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";string startupPath;string image_path;Stopwatch stopwatch = new Stopwatch();Mat image;Mat result_image;private void Form1_Load(object sender, EventArgs e){startupPath = System.Windows.Forms.Application.StartupPath;}private void button1_Click(object sender, EventArgs e){OpenFileDialog ofd = new OpenFileDialog();ofd.Filter = fileFilter;if (ofd.ShowDialog() != DialogResult.OK) return;pictureBox1.Image = null;pictureBox2.Image = null;textBox1.Text = "";image_path = ofd.FileName;pictureBox1.Image = new Bitmap(image_path);image = new Mat(image_path);}byte max2(byte a, byte b){return a > b ? a : b;}byte min2(byte a, byte b){return a < b ? a : b;}byte max3(byte a, byte b, byte c){return a > b ? max2(a, c) : max2(b, c);}byte min3(byte a, byte b, byte c){return a < b ? min2(a, c) : min2(b, c);}/// <summary>/// 饱和度/// </summary>/// <param name="src"></param>/// <param name="percent"></param>/// <returns></returns>unsafe Mat Saturation(Mat src, int percent){float Increment = percent * 1.0f / 100;Mat temp = src.Clone();int row = src.Rows;int col = src.Cols;for (int i = 0; i < row; ++i){byte* t = (byte*)temp.Ptr(i);byte* s = (byte*)src.Ptr(i);for (int j = 0; j < col; ++j){byte b = s[3 * j];byte g = s[3 * j + 1];byte r = s[3 * j + 2];float max = max3(r, g, b);float min = min3(r, g, b);float delta, value;float L, S, alpha;delta = (max - min) / 255;if (delta == 0)continue;value = (max + min) / 255;L = value / 2;if (L < 0.5)S = delta / value;elseS = delta / (2 - value);if (Increment >= 0){if ((Increment + S) >= 1)alpha = S;elsealpha = 1 - Increment;alpha = 1 / alpha - 1;t[3 * j + 2] = (byte)(r + (r - L * 255) * alpha);t[3 * j + 1] = (byte)(g + (g - L * 255) * alpha);t[3 * j] = (byte)(b + (b - L * 255) * alpha);}else{alpha = Increment;t[3 * j + 2] = (byte)(L * 255 + (r - L * 255) * (1 + alpha));t[3 * j + 1] = (byte)(L * 255 + (g - L * 255) * (1 + alpha));t[3 * j] = (byte)(L * 255 + (b - L * 255) * (1 + alpha));}}}return temp;}/// <summary>/// 明度/// </summary>/// <param name="src"></param>/// <param name="percent"></param>/// <returns></returns>unsafe Mat Lightness(Mat src, float percent){float alpha = percent / 100;alpha = Math.Max(-1.0f, Math.Min(1.0f, alpha));Mat temp = src.Clone();int row = src.Rows;int col = src.Cols;for (int i = 0; i < row; ++i){byte* t = (byte*)temp.Ptr(i);byte* s = (byte*)src.Ptr(i);for (int j = 0; j < col; ++j){byte b = s[3 * j];byte g = s[3 * j + 1];byte r = s[3 * j + 2];if (alpha >= 0){t[3 * j + 2] = (byte)(r * (1 - alpha) + 255 * alpha);t[3 * j + 1] = (byte)(g * (1 - alpha) + 255 * alpha);t[3 * j] = (byte)(b * (1 - alpha) + 255 * alpha);}else{t[3 * j + 2] = (byte)(r * (1 + alpha));t[3 * j + 1] = (byte)(g * (1 + alpha));t[3 * j] = (byte)(b * (1 + alpha));}}}return temp;}/// <summary>/// 对比度/// </summary>unsafe Mat Contrast(Mat src, int percent){float alpha = percent / 100.0f;alpha = Math.Max(-1.0f, Math.Min(1.0f, alpha));Mat temp = src.Clone();int row = src.Rows;int col = src.Cols;int thresh = 127;for (int i = 0; i < row; ++i){byte* t = (byte*)temp.Ptr(i);byte* s = (byte*)src.Ptr(i);for (int j = 0; j < col; ++j){byte b = s[3 * j];byte g = s[3 * j + 1];byte r = s[3 * j + 2];int newb, newg, newr;if (alpha == 1){t[3 * j + 2] = (byte)(r > thresh ? 255 : 0);t[3 * j + 1] = (byte)(g > thresh ? 255 : 0);t[3 * j] = (byte)(b > thresh ? 255 : 0);continue;}else if (alpha >= 0){newr = (int)(thresh + (r - thresh) / (1 - alpha));newg = (int)(thresh + (g - thresh) / (1 - alpha));newb = (int)(thresh + (b - thresh) / (1 - alpha));}else{newr = (int)(thresh + (r - thresh) * (1 + alpha));newg = (int)(thresh + (g - thresh) * (1 + alpha));newb = (int)(thresh + (b - thresh) * (1 + alpha));}newr = Math.Max(0, Math.Min(255, newr));newg = Math.Max(0, Math.Min(255, newg));newb = Math.Max(0, Math.Min(255, newb));t[3 * j + 2] = (byte)(newr);t[3 * j + 1] = (byte)(newg);t[3 * j] = (byte)(newb);}}return temp;}/// <summary>/// 图像阴影选取/// </summary>/// <param name="input"></param>/// <param name="light"></param>/// <returns></returns>unsafe Mat Shadow(Mat input, int light){// 生成灰度图Mat gray = Mat.Zeros(input.Size(), MatType.CV_32FC1);Mat f = input.Clone();f.ConvertTo(f, MatType.CV_32FC3);Mat[] pics = new Mat[3] { new Mat(), new Mat(), new Mat() };Cv2.Split(f, out pics);gray = 0.299f * pics[2] + 0.587 * pics[1] + 0.114 * pics[0];gray = gray / 255.0f;// 确定阴影区Mat thresh = Mat.Zeros(gray.Size(), gray.Type());thresh = (1.0f - gray).Mul(1.0f - gray);// 取平均值作为阈值Scalar t = Cv2.Mean(thresh);Mat mask = Mat.Zeros(gray.Size(), MatType.CV_8UC1);mask.SetTo(new Scalar(255), thresh.GreaterThanOrEqual(t.Val0));// 参数设置int max = 4;float bright = light / 100.0f / max;float mid = 1.0f + max * bright;// 边缘平滑过渡Mat midrate = Mat.Zeros(input.Size(), MatType.CV_32FC1);Mat brightrate = Mat.Zeros(input.Size(), MatType.CV_32FC1);for (int i = 0; i < input.Rows; ++i){byte* m = (byte*)mask.Ptr(i);float* th = (float*)thresh.Ptr(i);float* mi = (float*)midrate.Ptr(i);float* br = (float*)brightrate.Ptr(i);for (int j = 0; j < input.Cols; ++j){if (m[j] == 255){mi[j] = mid;br[j] = bright;}else{mi[j] = (float)((mid - 1.0f) / t[0] * th[j] + 1.0f);br[j] = (float)((1.0f / t[0] * th[j]) * bright);}}}// 阴影提亮,获取结果图Mat result = Mat.Zeros(input.Size(), input.Type());for (int i = 0; i < input.Rows; ++i){float* mi = (float*)midrate.Ptr(i);float* br = (float*)brightrate.Ptr(i);byte* @in = (byte*)input.Ptr(i);byte* r = (byte*)result.Ptr(i);for (int j = 0; j < input.Cols; ++j){for (int k = 0; k < 3; ++k){float temp = (float)(Math.Pow((float)(@in[3 * j + k]) / 255.0f, 1.0f / mi[j]) * (1.0 / (1 - br[j])));if (temp > 1.0f)temp = 1.0f;if (temp < 0.0f)temp = 0.0f;byte utemp = (byte)(255 * temp);r[3 * j + k] = utemp;}}}return result;}/// <summary>/// 图像高光选取/// </summary>/// <param name="input"></param>/// <param name="light"></param>/// <returns></returns>unsafe Mat HighLight(Mat input, int light){// 生成灰度图Mat gray = Mat.Zeros(input.Size(), MatType.CV_32FC1);Mat f = input.Clone();f.ConvertTo(f, MatType.CV_32FC3);Mat[] pics = new Mat[3] { new Mat(), new Mat(), new Mat() };Cv2.Split(f, out pics);gray = 0.299f * pics[2] + 0.587 * pics[1] + 0.114 * pics[0];gray = gray / 255.0f;// 确定高光区Mat thresh = Mat.Zeros(gray.Size(), gray.Type());thresh = gray.Mul(gray);// 取平均值作为阈值Scalar t = Cv2.Mean(thresh);Mat mask = Mat.Zeros(gray.Size(), MatType.CV_8UC1);mask.SetTo(new Scalar(255), thresh.GreaterThanOrEqual(t.Val0));// 参数设置int max = 4;float bright = light / 100.0f / max;float mid = 1.0f + max * bright;// 边缘平滑过渡Mat midrate = Mat.Zeros(input.Size(), MatType.CV_32FC1);Mat brightrate = Mat.Zeros(input.Size(), MatType.CV_32FC1);for (int i = 0; i < input.Rows; ++i){byte* m = (byte*)mask.Ptr(i);float* th = (float*)thresh.Ptr(i);float* mi = (float*)midrate.Ptr(i);float* br = (float*)brightrate.Ptr(i);for (int j = 0; j < input.Cols; ++j){if (m[j] == 255){mi[j] = mid;br[j] = bright;}else{mi[j] = (float)((mid - 1.0f) / t[0] * th[j] + 1.0f);br[j] = (float)((1.0f / t[0] * th[j]) * bright);}}}// 高光提亮,获取结果图Mat result = Mat.Zeros(input.Size(), input.Type());for (int i = 0; i < input.Rows; ++i){float* mi = (float*)midrate.Ptr(i);float* br = (float*)brightrate.Ptr(i);byte* @in = (byte*)input.Ptr(i);byte* r = (byte*)result.Ptr(i);for (int j = 0; j < input.Cols; ++j){for (int k = 0; k < 3; ++k){float temp = (float)(Math.Pow((float)(@in[3 * j + k]) / 255.0f, 1.0f / mi[j]) * (1.0 / (1 - br[j])));if (temp > 1.0f)temp = 1.0f;if (temp < 0.0f)temp = 0.0f;byte utemp = (byte)(255 * temp);r[3 * j + k] = utemp;}}}return result;}// 色温调节unsafe Mat ColorTemperature(Mat input, int n){Mat result = input.Clone();int row = input.Rows;int col = input.Cols;int level = n / 2;for (int i = 0; i < row; ++i){byte* a = (byte*)input.Ptr(i);byte* r = (byte*)result.Ptr(i);for (int j = 0; j < col; ++j){int R, G, B;// R通道R = a[j * 3 + 2];R = R + level;if (R > 255){r[j * 3 + 2] = 255;}else if (R < 0){r[j * 3 + 2] = 0;}else{r[j * 3 + 2] = (byte)R;}// G通道G = a[j * 3 + 1];G = G + level;if (G > 255){r[j * 3 + 1] = 255;}else if (G < 0){r[j * 3 + 1] = 0;}else{r[j * 3 + 1] = (byte)G;}// B通道B = a[j * 3];B = B - level;if (B > 255){r[j * 3] = 255;}else if (B < 0){r[j * 3] = 0;}else{r[j * 3] = (byte)B;}}}return result;}// 图像锐化unsafe Mat Sharpen(Mat input, int percent, int type){Mat result;Mat s = input.Clone();InputArray kernel;switch (type){case 0:kernel =InputArray.Create<float>(new float[3, 3] {{ 0, -1, 0 },{ -1, 4, -1 },{ 0, -1, 0 } });break;case 1:kernel =InputArray.Create<float>(new float[3, 3] {{  -1, -1, -1},{  -1, 8, -1 },{  -1, -1, -1 } });break;default:kernel =InputArray.Create<float>(new float[3, 3] {{  0, -1, 0},{  -1, 4, -1 },{  0, -1, 0 } });break;}Cv2.Filter2D(s, s, s.Depth(), kernel);result = input + s * 0.01 * percent;return result;}//天空滤镜private void button2_Click(object sender, EventArgs e){stopwatch.Restart();image_path = "test_img\\sky.jpg";pictureBox1.Image = new Bitmap(image_path);Mat src = Cv2.ImRead(image_path);Mat sat = Saturation(src, 35);Mat lig = Lightness(sat, 20);Mat con = Contrast(lig, 15);Mat sdo = Shadow(con, 15);Mat hig = HighLight(sdo, -30);result_image = ColorTemperature(hig, -40);double costTime = stopwatch.Elapsed.TotalMilliseconds;textBox1.Text = $"耗时:{costTime:F2}ms";pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());}private void button3_Click(object sender, EventArgs e){if (pictureBox2.Image == null){return;}Bitmap output = new Bitmap(pictureBox2.Image);var sdf = new SaveFileDialog();sdf.Title = "保存";sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp|Images (*.emf)|*.emf|Images (*.exif)|*.exif|Images (*.gif)|*.gif|Images (*.ico)|*.ico|Images (*.tiff)|*.tiff|Images (*.wmf)|*.wmf";if (sdf.ShowDialog() == DialogResult.OK){switch (sdf.FilterIndex){case 1:{output.Save(sdf.FileName, ImageFormat.Jpeg);break;}case 2:{output.Save(sdf.FileName, ImageFormat.Png);break;}case 3:{output.Save(sdf.FileName, ImageFormat.Bmp);break;}case 4:{output.Save(sdf.FileName, ImageFormat.Emf);break;}case 5:{output.Save(sdf.FileName, ImageFormat.Exif);break;}case 6:{output.Save(sdf.FileName, ImageFormat.Gif);break;}case 7:{output.Save(sdf.FileName, ImageFormat.Icon);break;}case 8:{output.Save(sdf.FileName, ImageFormat.Tiff);break;}case 9:{output.Save(sdf.FileName, ImageFormat.Wmf);break;}}MessageBox.Show("保存成功,位置:" + sdf.FileName);}}//人像—酷感冷艳滤镜private void button4_Click(object sender, EventArgs e){stopwatch.Restart();image_path = "test_img\\test01.jpg";pictureBox1.Image = new Bitmap(image_path);Mat src = Cv2.ImRead(image_path);Mat con = Contrast(src, 25);Mat lig = Lightness(con, -30);Mat hig = HighLight(lig, 20);Mat sha = Sharpen(hig, 50, 0);Mat sat = Saturation(sha, 20);result_image = ColorTemperature(hig, -40);double costTime = stopwatch.Elapsed.TotalMilliseconds;textBox1.Text = $"耗时:{costTime:F2}ms";pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());}//美食—鲜美滤镜private void button5_Click(object sender, EventArgs e){stopwatch.Restart();image_path = "test_img\\test02.jpg";pictureBox1.Image = new Bitmap(image_path);Mat src = Cv2.ImRead(image_path);Mat sat = Saturation(src, 25);Mat lig = Lightness(sat, 10);Mat con = Contrast(lig, 30);Mat sha = Sharpen(con, 30, 0);Mat sdo = Shadow(sha, -5);result_image = HighLight(sdo, 15);double costTime = stopwatch.Elapsed.TotalMilliseconds;textBox1.Text = $"耗时:{costTime:F2}ms";pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());}//美食—巧克力滤镜private void button6_Click(object sender, EventArgs e){stopwatch.Restart();image_path = "test_img\\test03.jpg";pictureBox1.Image = new Bitmap(image_path);Mat src = Cv2.ImRead(image_path);Mat sat = Saturation(src, 20);Mat lig = Lightness(sat, -15);Mat con = Contrast(lig, 35);Mat sha = Sharpen(con, 10, 0);Mat sdo = Shadow(sha, 25);result_image = HighLight(sdo, -5);double costTime = stopwatch.Elapsed.TotalMilliseconds;textBox1.Text = $"耗时:{costTime:F2}ms";pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());}}
}

参考 

OpenCV-美食—巧克力滤镜_opencv美食场景-CSDN博客

OpenCV-美食—鲜美滤镜_opencv实现美食滤镜—让食物更诱人-CSDN博客

OpenCV-人像—酷感冷艳滤镜_opencv和c++实现冷色调-CSDN博客

OpenCV-风景—天空滤镜_风景滤镜参数-CSDN博客

下载

源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/61764.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Easyexcel(4-模板文件)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09;Easyexcel&#xff08;4-模板文件&#xff09; 文件导出 获取 resources 目录下的文件&#xff0c;使用 withTemplate 获…

迁移学习理论与应用

迁移学习&#xff08;Transfer Learning&#xff09;是一种机器学习技术&#xff0c;旨在将一个任务&#xff08;源任务&#xff09;上学到的知识迁移到另一个相关但不完全相同的任务&#xff08;目标任务&#xff09;上&#xff0c;从而提高目标任务的学习效果。这种方法的核心…

近期两篇NeRF/3DGS-based SLAM方案赏析:TS-SLAM and MBA-SLAM

原文链接&#xff1a;近期两篇NeRF/3DGS-based SLAM方案赏析&#xff1a;TS-SLAM and MBA-SLAM paper1&#xff1a;TS-SLAM: 基于轨迹平滑约束优化的神经辐射场SLAM方法 导读 本文提出了TS-SLAM&#xff0c;一种改进的基于神经辐射场&#xff08;NeRF&#xff09;的SLAM方法…

游戏引擎学习第20天

视频参考:https://www.bilibili.com/video/BV1VkBCYmExt 解释 off-by-one 错误 从演讲者的视角&#xff1a;对代码问题的剖析与修复过程 问题的起因 演讲者提到&#xff0c;他可能无意中在代码中造成了一个错误&#xff0c;这与“调试时间标记索引”有关。他发现了一个逻辑问题…

《鸿蒙系统:开启智能新时代的璀璨之星》

一、鸿蒙系统&#xff1a;崛起之路 鸿蒙系统的发展历程堪称一部科技创新的传奇。2012 年&#xff0c;华为前瞻性地启动鸿蒙系统研发项目&#xff0c;彼时或许很少有人能预见到它未来的辉煌。2019 年&#xff0c;鸿蒙系统首个开发者预览版的发布&#xff0c;如同夜空中的一颗璀…

SQL注入--DNSlog外带注入--理论

什么是DNSlog? DNS的作用是将域名解析为IP 而DNSlog就是存储在DNS服务器上的域名信息&#xff0c;它记录着用户对域名访问信息。可以理解为DNS服务器上的日志文件。 多级域名 比如blog.csdn.net&#xff0c;以点为分隔&#xff0c;从右向左依次是顶级域名、二级域名、三级域…

python: Serialize and Deserialize complex JSON using jsonpickle

# encoding: utf-8 # 版权所有 2024 ©涂聚文有限公司 # 许可信息查看&#xff1a;言語成了邀功盡責的功臣&#xff0c;還需要行爲每日來值班嗎 # Serialize and Deserialize complex JSON in Python # 描述&#xff1a;pip install jsonpickle https://github.com/jsonpi…

基于图的去中心化社会推荐过滤器

目录 原论文研究背景与研究意义概述论文所提出算法的主要贡献GDSRec算法原理与流程问题定义去中心化图&#xff08;decentralized graph&#xff09;所提出方法(三种并行建模)用户建模&#xff08;user modelling&#xff09; 模版代码讲解main.py顶层文件&#xff1a;用于集成…

计算机的错误计算(一百六十三)

摘要 四个算式“sin(0.00024/2)^2”、“(1-cos(0.00024))/2”、“(1-sqrt(1-sin(0.00024)^2))/2”以及“sin(0.00024)^2/(22*sqrt(1-sin(0.00024)^2))”是等价的。但是&#xff0c;在 MATLAB 中计算它们&#xff0c;输出不完全一致&#xff1a;中间两个算式的输出中含有错误数…

递归算法专题一>Pow(x, n)

题目&#xff1a; 解析&#xff1a; 代码&#xff1a; public double myPow(double x, int n) {return n < 0 ? 1.0 / pow(x,-n) : pow(x,n); }private double pow(double x, int n){if(n 0) return 1.0;double tmp pow(x,n / 2);return n % 2 0 ? tmp * tmp : tmp …

论文阅读 SimpleNet: A Simple Network for Image Anomaly Detection and Localization

SimpleNet: A Simple Network for Image Anomaly Detection and Localization 摘要&#xff1a; 该论文提出了一个简单且应用友好的网络&#xff08;称为 SimpleNet&#xff09;来检测和定位异常。SimpleNet 由四个组件组成&#xff1a;&#xff08;1&#xff09;一个预先训练的…

实战分享:如何在HP-UX上高效扩容Oracle 12c RAC ASM磁盘

文章目录 Oracle 12c RAC ASM磁盘扩容 for HP-UX一、扩容原因二、扩容前信息三、扩容详细步骤3.1 存储划分LUN&#xff0c;映射到Oracle 12c RAC相关主机组3.2 扫描查看磁盘3.3 检查两节点间的磁盘盘符是否一致3.4 以一个节点为准同步磁盘盘符3.5 更改磁盘属主、权限3.6 查看AS…

如何使用 Matlab 制作 GrabCAD 体素打印切片

本教程适用于已经对 Matlab 和 J750 操作有所了解的用户。 它不是有关如何使用 Matlab 软件或 PolyJet 打印机的全面课程。 Stratasys 为您提供以下内容&#xff1a; 第 1 步&#xff1a;什么是体素&#xff1f; 就像 2D 数字图像由像素组成一样&#xff0c;您可以将 3D 数字形…

CNN—LeNet:从0开始神经网络学习,实战MNIST和CIFAR10~

文章目录 前言一、CNN与LeNet介绍二、LeNet组成及其名词解释2.1 输入2.2 卷积层2.3池化层2.4 全连接层2.5 总结 三、MNIST实战3.1 构建神经网络3.2 数据处理3.3 &#xff08;模板&#xff09;设置优化器&#xff0c;损失函数&#xff0c;使用gpu(如果是N卡有cuda核心)&#xff…

SpringBoot集成Dynamo(3)集成远程dynamo

按照推荐的AWS IAM SSO模式&#xff0c;以文件存储凭证的方式&#xff0c;看下代码是如何访问的。 pom依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"…

半导体、晶体管、集成电路、芯片、CPU、单片机、单片机最小系统、单片机开发板-概念串联辨析

下面概念定义从小到大串联&#xff1a; 半导体&#xff08;semiconductor&#xff09;&#xff1a; 是一类常温下导电性能介于导体与绝缘体之间的材料&#xff0c;这种材料的导电性可以随着外部环境比如电压、温度、光照的变换而改变。常见的半导体材料有硅、锗、砷化镓等。 晶…

学习路之phpstudy--安装mysql5.7后在my.ini文件中无法修改sql_mode

windows环境下使用phpstudy安装mysql5.7后需要修改mysql中的sql_mode配置&#xff0c;但是在phpstudy中打开mysql配置文件my.ini后&#xff0c; 通过查找找不到sql_mode或sql-mode&#xff0c; 此时无法在my.ini文件中直接进行修改&#xff0c;可以使用mysql命令进行修改&#…

了解大模型:开启智能科技的新篇章

在当今科技飞速发展的时代,人工智能(AI)已经成为推动社会进步的重要力量。而在AI的众多技术分支中,大模型(Large Model)以其强大的数据处理能力和卓越的性能,正逐渐成为研究和应用的热点。本文旨在科普大模型的基本概念、与大数据的关系以及与人工智能的紧密联系,帮助读…

多目标粒子群优化(Multi-Objective Particle Swarm Optimization, MOPSO)算法

概述 多目标粒子群优化&#xff08;MOPSO&#xff09; 是粒子群优化&#xff08;PSO&#xff09;的一种扩展&#xff0c;用于解决具有多个目标函数的优化问题。MOPSO的目标是找到一组非支配解&#xff08;Pareto最优解&#xff09;&#xff0c;这些解在不同目标之间达到平衡。…

联想ThinkServer服务器主要硬件驱动下载

联想ThinkServer服务器主要硬件驱动下载&#xff1a; 联想ThinkServer服务器主要硬件Windows Server驱动下载https://newsupport.lenovo.com.cn/commonProblemsDetail.html?noteid156404#D50