目录
效果
风景-天空滤镜
人像—酷感冷艳滤镜
美食—鲜美滤镜
美食—巧克力滤镜
项目
代码
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);
}
///
/// 饱和度
///
///
///
///
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;
}
///
/// 明度
///
///
///
///
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;
}
///
/// 对比度
///
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;
}
///
/// 图像阴影选取
///
///
///
///
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;
}
///
/// 图像高光选取
///
///
///
///
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
{ 0, -1, 0 },
{ -1, 4, -1 },
{ 0, -1, 0 } });
break;
case 1:
kernel =
InputArray.Create
{ -1, -1, -1},
{ -1, 8, -1 },
{ -1, -1, -1 } });
break;
default:
kernel =
InputArray.Create
{ 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;
- 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());
- }
- }
- }
参考
OpenCV-美食—巧克力滤镜_opencv美食场景-CSDN博客
OpenCV-美食—鲜美滤镜_opencv实现美食滤镜—让食物更诱人-CSDN博客
OpenCV-人像—酷感冷艳滤镜_opencv和c++实现冷色调-CSDN博客
下载


评论记录:
回复评论: