赞
踩
C# OpenCvSharp 实现Reinhard颜色迁移算法
目录
Reinhard颜色迁移算法的步骤:
1、将参考图片和目标图片转换到LAB空间下
2、得到参考图片和目标图片的均值和标准差
3、对目标图片的每一个像素值,减去目标图像均值然后乘上参考图片和目标图片标准差的比值,再加上参考图像均值
4、将目标图片转换到RGB空间
using OpenCvSharp;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
namespace OpenCvSharp_Demo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string fileFilter = "选择图片|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
string sc_image_path;
string dc_image_path;
Stopwatch stopwatch = new Stopwatch();
private void Form1_Load(object sender, EventArgs e)
{
sc_image_path = "1.jpg";
dc_image_path = "2.jpg";
pictureBox1.Image = new Bitmap(sc_image_path);
pictureBox3.Image = new Bitmap(dc_image_path);
}
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 = "";
sc_image_path = ofd.FileName;
pictureBox1.Image = new Bitmap(sc_image_path);
}
private void button4_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = fileFilter;
if (ofd.ShowDialog() != DialogResult.OK) return;
pictureBox3.Image = null;
pictureBox2.Image = null;
textBox1.Text = "";
dc_image_path = ofd.FileName;
pictureBox3.Image = new Bitmap(dc_image_path);
}
private void button2_Click(object sender, EventArgs e)
{
if (sc_image_path == "")
{
return;
}
if (dc_image_path == "")
{
return;
}
stopwatch.Restart();
Mat sc = Cv2.ImRead(sc_image_path, ImreadModes.Color);
Cv2.CvtColor(sc, sc, ColorConversionCodes.BGR2Lab);
Mat sc_m = new Mat();
Mat sc_sd = new Mat();
Cv2.MeanStdDev(sc, sc_m, sc_sd);
Mat dc = Cv2.ImRead(dc_image_path, ImreadModes.Color);
Cv2.CvtColor(dc, dc, ColorConversionCodes.BGR2Lab);
Mat dc_m = new Mat();
Mat dc_sd = new Mat();
Cv2.MeanStdDev(dc, dc_m, dc_sd);
var mat3 = new Mat<Vec3b>(sc);
var indexer = mat3.GetIndexer();
for (int y = 0; y < sc.Height; y++)
{
for (int x = 0; x < sc.Width; x++)
{
Vec3b color = indexer[y, x];
byte temp = color.Item0;
double dtemp = (temp - sc_m.At<double>(0, 0)) * (dc_sd.At<double>(0, 0) / sc_sd.At<double>(0, 0)) + dc_m.At<double>(0, 0);
dtemp = Math.Round(dtemp);
if (dtemp < 0)
{
dtemp = 0;
}
else if (dtemp > 255)
{
dtemp = 255;
}
byte temp1 = color.Item1;
double dtemp1 = ((byte)((temp1 - sc_m.At<double>(0, 1)) * (dc_sd.At<double>(0, 1) / sc_sd.At<double>(0, 1)) + dc_m.At<double>(0, 1)));
dtemp1 = Math.Round(dtemp1);
if (dtemp1 < 0)
{
dtemp1 = 0;
}
else if (dtemp1 > 255)
{
dtemp1 = 255;
}
byte temp2 = color.Item2;
double dtemp2 = ((byte)((temp2 - sc_m.At<double>(0, 2)) * (dc_sd.At<double>(0, 2) / sc_sd.At<double>(0, 2)) + dc_m.At<double>(0, 2)));
dtemp2 = Math.Round(dtemp2);
if (dtemp2 < 0)
{
dtemp2 = 0;
}
else if (dtemp2 > 255)
{
dtemp2 = 255;
}
color.Item0 = (byte)dtemp;
color.Item1 = (byte)dtemp1;
color.Item2 = (byte)dtemp2;
indexer[y, x] = color;
}
}
Cv2.CvtColor(sc, sc, ColorConversionCodes.Lab2BGR);
double costTime = stopwatch.Elapsed.TotalMilliseconds;
textBox1.Text = $"耗时:{costTime:F2}ms";
pictureBox2.Image = new Bitmap(sc.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";
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;
}
}
MessageBox.Show("保存成功,位置:" + sdf.FileName);
}
}
}
}
/*
Reinhard颜色迁移算法的过程
1、将参考图片和目标图片转换到LAB空间下
2、得到参考图片和目标图片的均值和标准差
3、对目标图片的每一个像素值,减去目标图像均值然后乘上参考图片和目标图片标准差的比值,再加上参考图像均值
4、将目标图片转换到RGB空间
*/
- using OpenCvSharp;
- using System;
- using System.Diagnostics;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Windows.Forms;
-
- namespace OpenCvSharp_Demo
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
-
- string fileFilter = "选择图片|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
- string sc_image_path;
- string dc_image_path;
-
- Stopwatch stopwatch = new Stopwatch();
-
- private void Form1_Load(object sender, EventArgs e)
- {
- sc_image_path = "1.jpg";
- dc_image_path = "2.jpg";
-
- pictureBox1.Image = new Bitmap(sc_image_path);
- pictureBox3.Image = new Bitmap(dc_image_path);
- }
-
- 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 = "";
-
- sc_image_path = ofd.FileName;
- pictureBox1.Image = new Bitmap(sc_image_path);
- }
-
- private void button4_Click(object sender, EventArgs e)
- {
- OpenFileDialog ofd = new OpenFileDialog();
- ofd.Filter = fileFilter;
- if (ofd.ShowDialog() != DialogResult.OK) return;
-
- pictureBox3.Image = null;
- pictureBox2.Image = null;
- textBox1.Text = "";
-
- dc_image_path = ofd.FileName;
- pictureBox3.Image = new Bitmap(dc_image_path);
- }
-
- private void button2_Click(object sender, EventArgs e)
- {
-
- if (sc_image_path == "")
- {
- return;
- }
-
- if (dc_image_path == "")
- {
- return;
- }
-
- stopwatch.Restart();
-
- Mat sc = Cv2.ImRead(sc_image_path, ImreadModes.Color);
- Cv2.CvtColor(sc, sc, ColorConversionCodes.BGR2Lab);
- Mat sc_m = new Mat();
- Mat sc_sd = new Mat();
- Cv2.MeanStdDev(sc, sc_m, sc_sd);
-
-
- Mat dc = Cv2.ImRead(dc_image_path, ImreadModes.Color);
- Cv2.CvtColor(dc, dc, ColorConversionCodes.BGR2Lab);
- Mat dc_m = new Mat();
- Mat dc_sd = new Mat();
- Cv2.MeanStdDev(dc, dc_m, dc_sd);
-
- var mat3 = new Mat<Vec3b>(sc);
- var indexer = mat3.GetIndexer();
-
- for (int y = 0; y < sc.Height; y++)
- {
- for (int x = 0; x < sc.Width; x++)
- {
- Vec3b color = indexer[y, x];
-
- byte temp = color.Item0;
- double dtemp = (temp - sc_m.At<double>(0, 0)) * (dc_sd.At<double>(0, 0) / sc_sd.At<double>(0, 0)) + dc_m.At<double>(0, 0);
- dtemp = Math.Round(dtemp);
- if (dtemp < 0)
- {
- dtemp = 0;
- }
- else if (dtemp > 255)
- {
- dtemp = 255;
- }
-
- byte temp1 = color.Item1;
- double dtemp1 = ((byte)((temp1 - sc_m.At<double>(0, 1)) * (dc_sd.At<double>(0, 1) / sc_sd.At<double>(0, 1)) + dc_m.At<double>(0, 1)));
- dtemp1 = Math.Round(dtemp1);
- if (dtemp1 < 0)
- {
- dtemp1 = 0;
- }
- else if (dtemp1 > 255)
- {
- dtemp1 = 255;
- }
-
- byte temp2 = color.Item2;
- double dtemp2 = ((byte)((temp2 - sc_m.At<double>(0, 2)) * (dc_sd.At<double>(0, 2) / sc_sd.At<double>(0, 2)) + dc_m.At<double>(0, 2)));
- dtemp2 = Math.Round(dtemp2);
- if (dtemp2 < 0)
- {
- dtemp2 = 0;
- }
- else if (dtemp2 > 255)
- {
- dtemp2 = 255;
- }
-
- color.Item0 = (byte)dtemp;
- color.Item1 = (byte)dtemp1;
- color.Item2 = (byte)dtemp2;
-
- indexer[y, x] = color;
- }
- }
-
- Cv2.CvtColor(sc, sc, ColorConversionCodes.Lab2BGR);
-
- double costTime = stopwatch.Elapsed.TotalMilliseconds;
-
- textBox1.Text = $"耗时:{costTime:F2}ms";
- pictureBox2.Image = new Bitmap(sc.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";
- 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;
- }
- }
- MessageBox.Show("保存成功,位置:" + sdf.FileName);
- }
- }
-
- }
- }
- /*
- Reinhard颜色迁移算法的过程
- 1、将参考图片和目标图片转换到LAB空间下
- 2、得到参考图片和目标图片的均值和标准差
- 3、对目标图片的每一个像素值,减去目标图像均值然后乘上参考图片和目标图片标准差的比值,再加上参考图像均值
- 4、将目标图片转换到RGB空间
- */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。