public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Mat chapter4Img = new Mat();
System.Windows.Forms.OpenFileDialog chapter1OFD = new System.Windows.Forms.OpenFileDialog();
private void ImageProcess()
{
if (chapter1OFD.ShowDialog() == System.Windows.Forms.DialogResult.OK)
chapter4Img = CvInvoke.Imread(chapter1OFD.FileName, LoadImageType.AnyColor | LoadImageType.AnyDepth);
Mat tempImg = new Mat();
HisttoGram1D ht1D = new HisttoGram1D();
if (chapter4Img.NumberOfChannels != 1)
{
processimg();
//CvInvoke.CvtColor(chapter4Img, tempImg, ColorConversion.Bgr2Gray);
////彩色转灰度
//CvInvoke.NamedWindow("AJpg", NamedWindowType.AutoSize);
//CvInvoke.Imshow("AJpg", tempImg);
}
else {
tempImg = chapter4Img.Clone();
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ImageProcess();
}
//定义函数,输入Mat图像,输出DenseHistogram对象
DenseHistogram[] getDenseHistogramDataOfImage(Mat inImg)
//这里的inImg深度暂定为byte
{
DenseHistogram[] dh = new DenseHistogram[3]
{ new DenseHistogram(256, new RangeF(0f, 255.1f)),
new DenseHistogram(256, new RangeF(0f, 255.1f)),
new DenseHistogram(256, new RangeF(0f, 255.1f)) };
if (inImg.NumberOfChannels==3)
{
dh[0].Calculate(new Image<Gray, byte>[] { inImg.ToImage<Bgr, byte>()[0] }, false, null);
dh[1].Calculate(new Image<Gray, byte>[] { inImg.ToImage<Bgr, byte>()[1] }, false, null);
dh[2].Calculate(new Image<Gray, byte>[] { inImg.ToImage<Bgr, byte>()[2] }, false, null);
} else
{
dh[0].Calculate(new Image<Gray, byte>[] { inImg.ToImage<Gray, byte>()[0] }, false, null);
dh[1] = null;
dh[2] = null;
}
return dh;
}
private void processimg()
{
if (chapter4Img.IsEmpty)
return;
var dhData = getDenseHistogramDataOfImage(chapter4Img);
//默认直方图256Bins,像素值方位[0.255]
RangeF[] minValueAndMaxVlue = new RangeF[3];
float minValue = 0.01f;
//忽略数量少于minValue的箱子,定义数值范围0-1
if (minValue < 0)
minValue = 0;
else if (minValue > 1)
minValue = 1;
minValue = chapter4Img.Rows * chapter4Img.Cols * minValue;
//计算得到最小箱子
for (int i = 0; i < dhData.Length; i++)
{
if (dhData[i] == null)
{
minValueAndMaxVlue[i].Max = minValueAndMaxVlue[i].Min = -1f;
//及不存在这个通道的数据
continue;
}
for (; minValueAndMaxVlue[i].Min < dhData[i].GetBinValues().Length; minValueAndMaxVlue[i].Min += 1)
{
if (dhData[i].GetBinValues()[(int)minValueAndMaxVlue[i].Min] > minValue)
break;
}
minValueAndMaxVlue[i].Max = dhData[i].GetBinValues().Length - 1;
for (; minValueAndMaxVlue[i].Max >= 0; minValueAndMaxVlue[i].Max -= 1)
{
if (dhData[i].GetBinValues()[(int)minValueAndMaxVlue[i].Max] > minValue)
break;
}
}
var lut = new Image<Bgr, byte>(256, 1);
List<byte[]> arrayData = new List<byte[]>();
arrayData.Add(new byte[256]);
arrayData.Add(new byte[256]);
arrayData.Add(new byte[256]);
if (chapter4Img.NumberOfChannels == 1)
{
for (int i = 0; i < 256; i++)
{
if (i < minValueAndMaxVlue[0].Min)
arrayData[0][i] = 0;
else if (i > minValueAndMaxVlue[0].Max)
arrayData[0][i] = 255;
else
arrayData[0][i] = (byte)Math.Round(255.0 * (i - minValueAndMaxVlue[0].Min) / (minValueAndMaxVlue[0].Max - minValueAndMaxVlue[0].Min));
}
}
else
//对每个通道进行计算,得到范围
{
for (int index = 0; index < 3; index++)
{
arrayData[index] = new byte[256];
for (int i = 0; i < 256; i++)
{
if (i < minValueAndMaxVlue[index].Min)
arrayData[index][i] = 0;
else if (i > minValueAndMaxVlue[0].Max)
arrayData[index][i] = 255;
else
arrayData[index][i] = (byte)Math.Round(255.0 * (i - minValueAndMaxVlue[index].Min) / (minValueAndMaxVlue[index].Max - minValueAndMaxVlue[0].Min));
}
}
}
for (int i = 0; i < 256; i++)
{
for (int j = 0; j < 3; j++)
{
lut.Data[0, i, j] = arrayData[j][i];
}
}
Mat resultImg = new Mat(); if (chapter4Img.NumberOfChannels == 1)
{ CvInvoke.LUT(chapter4Img, lut.Split()[0].Mat, resultImg); }
else { CvInvoke.LUT(chapter4Img, lut.Split()[0].Mat, resultImg); }
CvInvoke.NamedWindow("Based on One Channel (Blue)", NamedWindowType.Normal);
CvInvoke.Imshow("Based on One Channel (Blue)", resultImg);
//对所有的通道取同样的minValueAndMaxValue范围计算
arrayData.Add(new byte[256]);
//再加一个数组
int newMinValue = Math.Min((int)Math.Min(minValueAndMaxVlue[0].Min, minValueAndMaxVlue[1].Min), (int)minValueAndMaxVlue[2].Min);
int newMaxValue = Math.Max((int)Math.Max(minValueAndMaxVlue[0].Max, minValueAndMaxVlue[1].Max), (int)minValueAndMaxVlue[2].Max);
for (int i = 0; i < 256; i++)
{
if (i < newMinValue)
arrayData[3][i] = 0;
else if (i > newMaxValue)
arrayData[3][i] = (byte)((255.0 * (i - newMinValue) / (newMaxValue - newMinValue)));
}
var newLut = new Mat(1, 256, DepthType.Cv8U, 1);
newLut.SetTo(arrayData[3]);
if (chapter4Img.NumberOfChannels == 3)
{
CvInvoke.LUT(chapter4Img, newLut, resultImg);
CvInvoke.NamedWindow("Based on BGR three Channels", NamedWindowType.KeepRatio);
CvInvoke.Imshow("Based on BGR three Channels", resultImg);
}
else
{
CvInvoke.LUT(chapter4Img, lut.Split()[0].Mat, resultImg);
CvInvoke.NamedWindow("Based on One Channel", NamedWindowType.KeepRatio);
CvInvoke.Imshow("Based on One Channel", resultImg);
}
}
}
public class HisttoGram1D
{
private int[] channels = new int[1];
//使用的通道index
int[] histSize = new int[1];//bin数量
RangeF[] ranges = new RangeF[1];//像素值范围
Mat mask = new Mat();//掩码
Mat hist = new Mat();//得到的直方图数据
public HisttoGram1D()
{
channels[0] = 0;
histSize[0] = 256;
ranges[0] = new RangeF(0.0f, 255.1f);
}
public DenseHistogram getDenseHistogram(Mat inImg)
{
if (inImg.IsEmpty)
{
return null;
}
DenseHistogram dh = new DenseHistogram(histSize, ranges);
var imgs = inImg.ToImage<Gray, byte>().Split();
dh.Calculate(imgs, false, null);
//计算直方图信息
return dh;
}
}