using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using PaintDotNet.Base.SettingModel;
using TUCAMAPI;
using TUCamera;
using OpenCvSharp;
using PaintDotNet.CustomControl;
namespace PaintDotNet.Setting.LabelComponent
{
public class DisplayCameraControl : UserControl
{
#region 初始化变量
private AppWorkspace AppWorkspace;
///
/// 一个矩阵数组,用来接收直方图,记得全部初始化
///
Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };
///
/// 相机采集的图像
///
Mat OldMat;
///
/// 灰度图
///
private bool isGray = true;
///
/// BGR线条颜色
///
private Scalar[] color = new Scalar[] { new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255), new Scalar(0, 0, 255, 255) };
public int trackBar1Value = -50;//亮度
public int trackBar2Value = 100;//对比度
public int trackBar3Value = 100;//gamma值
#endregion
#region 控件
private Label label0005;
///
/// 相机参数的Model
///
private CameraParamModel m_cameraParamModel;
private bool m_immediately;
private TUCamera.TUCamera m_camera;
private Label label7;
private TriangleTrackBar trackBar3;
private Label label6;
private TriangleTrackBar trackBar2;
private Label label5;
private TriangleTrackBar trackBar1;
private Label label4;
private NumericUpDown numericUpDown1;
private Label label3;
private Label label2;
private Label label1;
public Button button5;
public Button button4;
public Button button3;
public Button button2;
private UCTrackBar ucTrackBar1;
private SelectButton logButton;
private SelectButton skipButton;
private PictureBox pictureBox1;
private System.Timers.Timer m_aeTimer;
#endregion
public DisplayCameraControl(CameraParamModel model, bool immediately)
{
m_cameraParamModel = model;
m_immediately = immediately;
m_camera = TUCameraManager.GetInstance().GetCurrentCamera();
InitializeComponent();
InitializeLanguageText();
InitColorAdjustRange();
InitializeControlData();
}
///
/// 设置直方图的图像
///
///
public void resetMat(OpenCvSharp.Mat mat)
{
OldMat = mat;
if (this.OldMat == null)
{
isGray = true;
return;
}
isGray = true;
Mat[] mats = Cv2.Split(this.OldMat);//一张图片,将panda拆分成3个图片装进mat
Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
Mat[] mats1;
if (mats.Length < 2)
mats1 = new Mat[] { mats[0] };//panda的第二个通道,也就是G
else
mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
Mat[] mats2;
if (mats.Length < 3)
mats2 = new Mat[] { mats[0] };//panda的第三个通道,也就是R
else
mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
int[] channels1 = new int[] { 0 };
int[] channels2 = new int[] { 0 };
int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
for (int h = 0; h < oldHists[0].Rows; h++)
{
for (int j = oldHists.Length - 1; j >= 1; j--)
{
if (oldHists[j].At(h) != oldHists[0].At(h))
{
isGray = false;
break;
}
}
if (!isGray)
break;
}
//if (this.AppWorkspace.ActiveDocumentWorkspace != null)
//{
// //获取gamma值
// double gamma = this.AppWorkspace.ActiveDocumentWorkspace.HistogramGamma;
// this.trackBar3.Value = Math.Min(299, (int)(gamma * 100));//备注:需要与AxioVision进行比较效果,调试一致
// label7.Text = gamma.ToString("f2");
// //获取对比度
// double alpha = this.AppWorkspace.ActiveDocumentWorkspace.HistogramAlpha;
// //获取亮度
// double beta = this.AppWorkspace.ActiveDocumentWorkspace.HistogramBeta;
// //计算对比度
// label6.Text = alpha.ToString("f2");
// trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
// //计算亮度
// if (beta != double.Parse(label5.Text))
// {
// label5.Text = beta.ToString("f2");
// trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
// }
// this.numericUpDown1.Value = new decimal(new int[] {
//(int)this.AppWorkspace.ActiveDocumentWorkspace.HistogramPercent,
//0,
//0,
//0});
// //numericUpDown1.Value = (decimal)this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramPercent;
// skipButton.BtnSelect = this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled;
// logButton.BtnSelect = this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled;
//}
updateHistImg(null);
updateHistogramRect(true);
}
public void ResetCameraParamModel(CameraParamModel model)
{
m_cameraParamModel = model;
InitColorAdjustRange();
InitializeControlData();
}
int resolution_width = 2448;
int resolution_height = 2048;
private void InitColorAdjustRange()
{
//if (m_camera.IsOpen())
//{
// // 曝光时间
// double aeMinVal = 0;
// double aeMaxVal = 0;
// double aeDftVal = 0;
// m_camera.GetExposureTimeRange(ref aeMinVal, ref aeMaxVal, ref aeDftVal);
// m_camera.m_drawAllHandler += new DrawAllHandler(CallbackDraw);
// m_camera.StartWaitForFrame();
// m_process = m_camera.StartDrawing(ref resolution_width, ref resolution_height);
//}
}
////#17904
//private OpenCvSharp.Mat m_mat;
/////
///// 一个矩阵数组,用来接收直方图,记得全部初始化
/////
//Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };
/////
///// 灰度图
/////
//private bool isGray = true;
/////
///// BGR线条颜色
/////
//private Scalar[] color = new Scalar[] { new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255), new Scalar(0, 0, 255, 255) };
/////
///// skip按钮
///// 显示直方图时,忽略黑色的灰度或颜色值。
///// 这使您可以为背景为黑色的图像实现有意义的直方图显示。
/////
/////
/////
//private void skipButton_Click(object sender, EventArgs e)
//{
// if (m_mat == null)
// {
// //MessageBox.Show("请打开图片");
// return;
// }
// //设置按钮的选中/非选择的状态
// skip000Button.BtnSelect = !skip000Button.BtnSelect;
// //this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled = skipButton.BtnSelect;
// updateHistImg(null);
//}
/////
///// log按钮
///// 以对数比例显示直方图
/////
/////
/////
//private void logButton_Click(object sender, EventArgs e)
//{
// if (m_mat == null)
// {
// //MessageBox.Show("请打开图片");
// return;
// }
// //设置按钮的选中/非选择的状态
// log000Button.BtnSelect = !log000Button.BtnSelect;
// //this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled = logButton.BtnSelect;
// updateHistImg(null);
//}
/////
///// 绘制
/////
/////
/////
//public void CallbackDraw(byte[] pBuf, object obj, int channel)
//{
// lock (obj)
// {
// //m_isWaiting = false;
// Console.WriteLine("接收全图buf");
// m_camera.m_drawAllHandler -= new DrawAllHandler(CallbackDraw);
// OpenCvSharp.Mat mat;
// if (channel == 1)
// {
// mat = new OpenCvSharp.Mat(resolution_height, resolution_width/*m_resolution.Height, m_resolution.Width*/, OpenCvSharp.MatType.CV_8UC1, pBuf);
// }
// else
// {
// mat = new OpenCvSharp.Mat(resolution_height, resolution_width/*m_resolution.Height, m_resolution.Width*/, OpenCvSharp.MatType.CV_8UC3, pBuf);
// }
// OpenCvSharp.Cv2.Flip(mat, mat, 0);
// if (m_mat != null)
// {
// m_mat.Dispose();
// }
// m_mat = mat.Clone();
// //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
// stopDrawing();
// if (mat != null)
// {
// mat.Dispose();
// }
// this.showHistImg(m_mat);
// }
//}
//private void showHistImg(Mat BoxMat)
//{
// Mat[] mats = Cv2.Split(BoxMat);//一张图片,将panda拆分成3个图片装进mat
// if (mats.Count() == 1)
// {
// isGray = true;
// }
// else
// {
// isGray = false;
// }
// if (isGray)
// {
// Mat[] mats011 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
// int[] channels011 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
// int[] histsize11 = new int[] { 256 };//一个通道,初始化为256箱子
// Rangef[] range11 = new Rangef[1];//一个通道,范围
// range11[0].Start = 0.0F;//从0开始(含)
// range11[0].End = 256.0F;//到256结束(不含)
// Mat mask11 = new Mat();//不做掩码
// Cv2.CalcHist(mats011, channels011, mask11, oldHists[0], 1, histsize11, range11);//对被拆分的图片单独进行计算
// updateHistImgGray(oldHists);
// return;
// }
// Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
// Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
// Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
// int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
// int[] channels1 = new int[] { 0 };
// int[] channels2 = new int[] { 0 };
// int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
// Rangef[] range = new Rangef[1];//一个通道,范围
// range[0].Start = 0.0F;//从0开始(含)
// range[0].End = 256.0F;//到256结束(不含)
// Mat mask = new Mat();//不做掩码
// Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
// Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
// Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
// for (int h = 0; h < oldHists[0].Rows; h++)
// {
// for (int j = oldHists.Length - 1; j >= 1; j--)
// {
// if (oldHists[j].At(h) != oldHists[0].At(h))
// {
// isGray = false;
// break;
// }
// }
// if (!isGray)
// break;
// }
// updateHistImg(oldHists);
//}
/////
///// 绘制直方图-单通道
/////
/////
/////
//private unsafe void updateHistImgGray(Mat[] hists)
//{
// if (m_mat == null)
// {
// return;
// }
// Mat[] mats = Cv2.Split(m_mat);//一张图片,将panda拆分成3个图片装进mat
// //if (mats.Count() == 1)
// //{
// // isGray = true;
// //}
// //else
// //{
// // isGray = false;
// //}
// Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
// //Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
// //Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
// if (hists == null)
// {
// hists = new Mat[] { new Mat()/*, new Mat(), new Mat()*/ };//一个矩阵数组,用来接收直方图,记得全部初始化
// int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
// //int[] channels1 = new int[] { 0 };
// //int[] channels2 = new int[] { 0 };
// int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
// Rangef[] range = new Rangef[1];//一个通道,范围
// range[0].Start = 0.0F;//从0开始(含)
// range[0].End = 256.0F;//到256结束(不含)
// Mat mask = new Mat();//不做掩码
// Cv2.CalcHist(mats0, channels0, mask, hists[0], 1, histsize, range);//对被拆分的图片单独进行计算
// //Cv2.CalcHist(mats1, channels1, mask, hists[1], 1, histsize, range);//对被拆分的图片单独进行计算
// //Cv2.CalcHist(mats2, channels2, mask, hists[2], 1, histsize, range);//对被拆分的图片单独进行计算
// if (log000Button.BtnSelect)
// {
// //取对数
// for (int j = 0; j < hists.Length; j++)
// {
// List ProbPixel = new List();
// for (int i = 0; i < hists[j].Rows; i++)
// {
// if (((float*)hists[j].Ptr(0))[i] == 0)
// {
// ((float*)hists[j].Ptr(0))[i] = ((float*)hists[j].Ptr(0))[i];
// ProbPixel.Add(0);
// }
// else
// {
// ((float*)hists[j].Ptr(0))[i] = (float)Math.Log10(((float*)hists[j].Ptr(0))[i]/* + 9*/);
// ProbPixel.Add(1);
// }
// }
// double max1jVal = 0;
// double min1jVal = 0;
// //找到直方图中的最大值和最小值
// Cv2.MinMaxLoc(hists[j], out min1jVal, out max1jVal);
// if (min1jVal >= max1jVal)
// {
// continue;
// }
// //归一化到0~255,并根据AxioVision添加偏置值
// for (int i = 0; i < hists[j].Rows; i++)
// {
// ((float*)hists[j].Ptr(0))[i] = (float)((((float*)hists[j].Ptr(0))[i] - 0) * 255.0 / (max1jVal - 0)) + (float)(min1jVal > 0 ? (ProbPixel[i] * min1jVal * 255.0 / max1jVal) : ProbPixel[i] * 5);
// }
// }
// }
// if (skip000Button.BtnSelect)
// {
// //去掉黑色部分 和 白色部分
// for (int j = 0; j < hists.Length; j++)
// {
// ((float*)hists[j].Ptr(0))[0] = 0;
// ((float*)hists[j].Ptr(0))[255] = 0;
// }
// }
// }
// //double max2Val = 0;
// //double max1Val = 0;
// double max0Val = 0;
// double minVal = 0;
// //为了更好显示直方图细节,使用4倍尺寸绘制直方图
// int histSize = hists[0].Rows * 4;
// Mat histImg = new Mat(histSize, histSize, MatType.CV_8UC3, new Scalar(255, 255, 255));
// //找到直方图中的最大值和最小值
// //Cv2.MinMaxLoc(hists[2], out minVal, out max2Val);
// //Cv2.MinMaxLoc(hists[1], out minVal, out max1Val);
// Cv2.MinMaxLoc(hists[0], out minVal, out max0Val);
// double maxVal = max0Val;// Math.Max(max2Val, Math.Max(max0Val, max1Val));
// if (maxVal < 1)
// return;
// // 设置最大峰值为图像高度的90%
// double hpt = 0.9 * histSize;
// //灰度图的显示直方图较为简单,显示一个通道即可
// if (isGray)
// {
// Mat hist = hists[0];
// int lastY2 = histSize - 1;
// for (int h = 0; h < hists[0].Rows; h++)
// {
// int intensity = (int)(hist.At(h) * hpt / maxVal);
// int lastY1 = lastY2;
// lastY2 = histSize - intensity - 1 - (hist.At(h) > 0 ? 4 : 0);
// if (lastY2 < lastY1)
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), new Scalar(0, 0, 0, 255), 2, LineTypes.Link4);
// }
// else
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lastY1 + 2)), new Scalar(0, 0, 0, 255), 2, LineTypes.Link4);
// }
// }
// }
// //彩度图显示BGR三个通道的直方图
// else
// {
// int lineWidth = 2;
// for (int j = hists.Length - 1; j >= 0; j--)
// {
// Mat hist = hists[j];
// int lastY2 = histSize - 1;
// for (int h = 0; h < hists[0].Rows; h++)
// {
// int intensity = (int)(hist.At(h) * hpt / maxVal);
// int lastY1 = lastY2;
// lastY2 = histSize - intensity - 1 - (hist.At(h) > 0 ? 4 : 0);
// if (h > 0)
// {
// //显示0.5位置的直方图,这样与AxioVision效果更加近似
// int lasty12 = (lastY1 + lastY2) / 2;
// if (lasty12 < lastY1)
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4 - 2, lastY1), new OpenCvSharp.Point(h * 4 - 2, Math.Min(lasty12, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
// }
// else
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4 - 2, lastY1), new OpenCvSharp.Point(h * 4 - 2, Math.Max(lasty12, lastY1 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
// }
// if (lastY2 < lasty12)
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lasty12 - 2)), color[j], lineWidth, LineTypes.Link4);
// }
// else
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lasty12 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
// }
// }
// else
// {
// //灰度值为0的线的绘制
// if (lastY2 < lastY1)
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
// }
// else
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lastY1 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
// }
// }
// }
// }
// }
// this.picture000Box1.BackgroundImage/*Image*/ = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
//}
/////
///// 绘制直方图
/////
/////
/////
//private unsafe void updateHistImg(Mat[] hists)
//{
// if (m_mat == null)
// {
// return;
// }
// Mat[] mats = Cv2.Split(m_mat);//一张图片,将panda拆分成3个图片装进mat
// if (mats.Count() == 1)
// {
// isGray = true;
// }
// else
// {
// isGray = false;
// }
// if (isGray)
// {
// updateHistImgGray(hists);
// return;
// }
// Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
// Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
// Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
// if (hists == null)
// {
// hists = new Mat[] { new Mat(), new Mat(), new Mat() };//一个矩阵数组,用来接收直方图,记得全部初始化
// int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
// int[] channels1 = new int[] { 0 };
// int[] channels2 = new int[] { 0 };
// int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
// Rangef[] range = new Rangef[1];//一个通道,范围
// range[0].Start = 0.0F;//从0开始(含)
// range[0].End = 256.0F;//到256结束(不含)
// Mat mask = new Mat();//不做掩码
// Cv2.CalcHist(mats0, channels0, mask, hists[0], 1, histsize, range);//对被拆分的图片单独进行计算
// Cv2.CalcHist(mats1, channels1, mask, hists[1], 1, histsize, range);//对被拆分的图片单独进行计算
// Cv2.CalcHist(mats2, channels2, mask, hists[2], 1, histsize, range);//对被拆分的图片单独进行计算
// if (log000Button.BtnSelect)
// {
// //取对数
// for (int j = 0; j < hists.Length; j++)
// {
// List ProbPixel = new List();
// for (int i = 0; i < hists[j].Rows; i++)
// {
// if (((float*)hists[j].Ptr(0))[i] == 0)
// {
// ((float*)hists[j].Ptr(0))[i] = ((float*)hists[j].Ptr(0))[i];
// ProbPixel.Add(0);
// }
// else
// {
// ((float*)hists[j].Ptr(0))[i] = (float)Math.Log10(((float*)hists[j].Ptr(0))[i]/* + 9*/);
// ProbPixel.Add(1);
// }
// }
// double max1jVal = 0;
// double min1jVal = 0;
// //找到直方图中的最大值和最小值
// Cv2.MinMaxLoc(hists[j], out min1jVal, out max1jVal);
// if (min1jVal >= max1jVal)
// {
// continue;
// }
// //归一化到0~255,并根据AxioVision添加偏置值
// for (int i = 0; i < hists[j].Rows; i++)
// {
// ((float*)hists[j].Ptr(0))[i] = (float)((((float*)hists[j].Ptr(0))[i] - 0) * 255.0 / (max1jVal - 0)) + (float)(min1jVal > 0 ? (ProbPixel[i] * min1jVal * 255.0 / max1jVal) : ProbPixel[i] * 5);
// }
// }
// }
// if (skip000Button.BtnSelect)
// {
// //去掉黑色部分 和 白色部分
// for (int j = 0; j < hists.Length; j++)
// {
// ((float*)hists[j].Ptr(0))[0] = 0;
// ((float*)hists[j].Ptr(0))[255] = 0;
// }
// }
// }
// double max2Val = 0;
// double max1Val = 0;
// double max0Val = 0;
// double minVal = 0;
// //为了更好显示直方图细节,使用4倍尺寸绘制直方图
// int histSize = hists[0].Rows * 4;
// Mat histImg = new Mat(histSize, histSize, MatType.CV_8UC3, new Scalar(255, 255, 255));
// //找到直方图中的最大值和最小值
// Cv2.MinMaxLoc(hists[2], out minVal, out max2Val);
// Cv2.MinMaxLoc(hists[1], out minVal, out max1Val);
// Cv2.MinMaxLoc(hists[0], out minVal, out max0Val);
// double maxVal = Math.Max(max2Val, Math.Max(max0Val, max1Val));
// if (maxVal < 1)
// return;
// // 设置最大峰值为图像高度的90%
// double hpt = 0.9 * histSize;
// //灰度图的显示直方图较为简单,显示一个通道即可
// if (isGray)
// {
// Mat hist = hists[0];
// int lastY2 = histSize - 1;
// for (int h = 0; h < hists[0].Rows; h++)
// {
// int intensity = (int)(hist.At(h) * hpt / maxVal);
// int lastY1 = lastY2;
// lastY2 = histSize - intensity - 1 - (hist.At(h) > 0 ? 4 : 0);
// if (lastY2 < lastY1)
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), new Scalar(0, 0, 0, 255), 2, LineTypes.Link4);
// }
// else
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lastY1 + 2)), new Scalar(0, 0, 0, 255), 2, LineTypes.Link4);
// }
// }
// }
// //彩度图显示BGR三个通道的直方图
// else
// {
// int lineWidth = 2;
// for (int j = hists.Length - 1; j >= 0; j--)
// {
// Mat hist = hists[j];
// int lastY2 = histSize - 1;
// for (int h = 0; h < hists[0].Rows; h++)
// {
// int intensity = (int)(hist.At(h) * hpt / maxVal);
// int lastY1 = lastY2;
// lastY2 = histSize - intensity - 1 - (hist.At(h) > 0 ? 4 : 0);
// if (h > 0)
// {
// //显示0.5位置的直方图,这样与AxioVision效果更加近似
// int lasty12 = (lastY1 + lastY2) / 2;
// if (lasty12 < lastY1)
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4 - 2, lastY1), new OpenCvSharp.Point(h * 4 - 2, Math.Min(lasty12, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
// }
// else
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4 - 2, lastY1), new OpenCvSharp.Point(h * 4 - 2, Math.Max(lasty12, lastY1 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
// }
// if (lastY2 < lasty12)
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lasty12 - 2)), color[j], lineWidth, LineTypes.Link4);
// }
// else
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lasty12 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
// }
// }
// else
// {
// //灰度值为0的线的绘制
// if (lastY2 < lastY1)
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
// }
// else
// {
// Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lastY1 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
// }
// }
// }
// }
// }
// this.picture000Box1.BackgroundImage/*Image*/ = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
//}
//private void stopDrawing()
//{
// //创建一个委托,用于封装一个方法,在这里是封装了 控制更新控件 的方法
// Action invokeAction = new Action(stopDrawing);
// //判断操作控件的线程是否创建控件的线程
// //调用方调用方位于创建控件所在的线程以外的线程中,如果在其他线程则对控件进行方法调用时必须调用 Invoke 方法
// if (this.InvokeRequired)
// {
// //与调用线程不同的线程上创建(说明您必须通过 Invoke 方法对控件进行调用)
// this.Invoke(invokeAction);
// }
// else
// {
// m_camera.StopDrawing(m_process);
// m_camera.StopWaitForFrame();
// ////窗体线程,即主线程
// //shuaxinButton.Enabled = true;
// }
//}
private string UpdateExposureTime(UInt64 exposureTime)
{
string str = "";
int sec = 0;
int msec = 0;
int usec = 0;
m_camera.UpdateExposureTime(ref sec, ref msec, ref usec, exposureTime);
if (sec > 0)
{
str += sec + "s";
}
else if (msec > 0)
{
str += msec + "ms";
}
else if (usec > 0)
{
str += usec + "μs";
}
return str;
}
private void UpdateExposureUI(int autoExposure)
{
if (autoExposure == 1)
{
// 设置到相机
if (m_immediately)
{
// 自动曝光
m_camera.SetExposureMode(ExposureMode.AUTO);
m_aeTimer.Start();
}
}
else
{
// 设置到相机
if (m_immediately)
{
m_camera.SetExposureMode(ExposureMode.MANUAL);
m_aeTimer.Stop();
}
}
}
///
/// 设置下拉等数据源
///
private void InitializeControlData()
{
m_aeTimer = new System.Timers.Timer(1000);
m_aeTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerAutoExposure);
m_aeTimer.AutoReset = true;
m_aeTimer.SynchronizingObject = this;
UpdateExposureUI(m_cameraParamModel.parame.ATExposure);
// 增益值调整
int gainValue = m_cameraParamModel.parame.GlobalGain;
//// 白平衡
//if (m_cameraParamModel.parame.WhiteBalance == 1)
//{
// AutoWhiteBalance(true);
//}
//else
//{
// if (m_cameraParamModel.parame.FMExposure == 1)
// {
// m_camera.SetColorTemperatureByString("3200K");
// }
// else if (m_cameraParamModel.parame.FMExposure == 2)
// {
// m_camera.SetColorTemperatureByString("5500K");
// }
// AutoWhiteBalance(false);
//}
}
private void InitializeLanguageText()
{
this.label0005.Text = PdnResources.GetString("Menu.timeofexposure.text")+":";
this.label3.Text = PdnResources.GetString("Menu.Gammavalue.text")+":";
this.label2.Text = PdnResources.GetString("Menu.Contrast.text")+":";
this.label1.Text = PdnResources.GetString("Menu.luminance.text")+":";
this.button5.Text = PdnResources.GetString("Menu.Originalstate.text");
this.button4.Text = PdnResources.GetString("Menu.Gammavalue.text")+"0.45";
this.button2.Text = PdnResources.GetString("Menu.optimal.text");
}
private void InitializeComponent()
{
this.label0005 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.trackBar3 = new PaintDotNet.CustomControl.TriangleTrackBar();
this.label6 = new System.Windows.Forms.Label();
this.trackBar2 = new PaintDotNet.CustomControl.TriangleTrackBar();
this.label5 = new System.Windows.Forms.Label();
this.trackBar1 = new PaintDotNet.CustomControl.TriangleTrackBar();
this.label4 = new System.Windows.Forms.Label();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.button5 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.ucTrackBar1 = new PaintDotNet.CustomControl.UCTrackBar();
this.logButton = new PaintDotNet.CustomControl.SelectButton();
this.skipButton = new PaintDotNet.CustomControl.SelectButton();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// label0005
//
this.label0005.AutoSize = true;
this.label0005.Location = new System.Drawing.Point(24, 39);
this.label0005.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label0005.Name = "label0005";
this.label0005.Size = new System.Drawing.Size(82, 15);
this.label0005.TabIndex = 12;
this.label0005.Text = "曝光时间:";
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(332, 237);
this.label7.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(29, 12);
this.label7.TabIndex = 59;
this.label7.Text = "1.00";
this.label7.TextChanged += new System.EventHandler(this.label7_Changed);
//
// trackBar3
//
this.trackBar3.Location = new System.Drawing.Point(127, 229);
this.trackBar3.Maximum = 299;
this.trackBar3.Minimum = 0;
this.trackBar3.Name = "trackBar3";
this.trackBar3.Size = new System.Drawing.Size(200, 30);
this.trackBar3.TabIndex = 58;
this.trackBar3.Value = 100;
this.trackBar3.TrackBarScroll += new System.EventHandler(this.trackBar3_Scroll);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(332, 201);
this.label6.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(29, 12);
this.label6.TabIndex = 57;
this.label6.Text = "1.00";
this.label6.TextChanged += new System.EventHandler(this.label6_Changed);
//
// trackBar2
//
this.trackBar2.Location = new System.Drawing.Point(127, 194);
this.trackBar2.Maximum = 999;
this.trackBar2.Minimum = 0;
this.trackBar2.Name = "trackBar2";
this.trackBar2.Size = new System.Drawing.Size(200, 30);
this.trackBar2.TabIndex = 56;
this.trackBar2.Value = 100;
this.trackBar2.TrackBarScroll += new System.EventHandler(this.trackBar2_Scroll);
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(332, 165);
this.label5.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(29, 12);
this.label5.TabIndex = 55;
this.label5.Text = "-0.5";
this.label5.TextChanged += new System.EventHandler(this.label5_Changed);
//
// trackBar1
//
this.trackBar1.Location = new System.Drawing.Point(127, 158);
this.trackBar1.Maximum = 200;
this.trackBar1.Minimum = -200;
this.trackBar1.Name = "trackBar1";
this.trackBar1.Size = new System.Drawing.Size(200, 30);
this.trackBar1.TabIndex = 54;
this.trackBar1.Value = -50;
this.trackBar1.TrackBarScroll += new System.EventHandler(this.trackBar1_Scroll);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(356, 279);
this.label4.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(17, 12);
this.label4.TabIndex = 53;
this.label4.Text = "‰";
//
// numericUpDown1
//
this.numericUpDown1.Location = new System.Drawing.Point(302, 275);
this.numericUpDown1.Margin = new System.Windows.Forms.Padding(2);
this.numericUpDown1.Maximum = new decimal(new int[] {
499,
0,
0,
0});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(50, 21);
this.numericUpDown1.TabIndex = 52;
this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
this.numericUpDown1.Value = new decimal(new int[] {
200,
0,
0,
0});
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(73, 237);
this.label3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(53, 12);
this.label3.TabIndex = 51;
this.label3.Text = "伽马值:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(73, 201);
this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(53, 12);
this.label2.TabIndex = 50;
this.label2.Text = "对比度:";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(85, 165);
this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(41, 12);
this.label1.TabIndex = 49;
this.label1.Text = "亮度:";
//
// button5
//
this.button5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.button5.Location = new System.Drawing.Point(184, 305);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(75, 23);
this.button5.TabIndex = 48;
this.button5.Text = "原始状态";
this.button5.UseVisualStyleBackColor = true;
this.button5.Click += new System.EventHandler(this.button5_Click);
//
// button4
//
this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.button4.Location = new System.Drawing.Point(70, 305);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(75, 23);
this.button4.TabIndex = 47;
this.button4.Text = "伽马值0.45";
this.button4.UseVisualStyleBackColor = true;
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// button3
//
this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.button3.Location = new System.Drawing.Point(299, 305);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(75, 23);
this.button3.TabIndex = 46;
this.button3.Text = "MIN/MAX";
this.button3.UseVisualStyleBackColor = true;
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.button2.Location = new System.Drawing.Point(184, 272);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 45;
this.button2.Text = "最佳";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// ucTrackBar1
//
this.ucTrackBar1.DcimalDigits = 0;
this.ucTrackBar1.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(77)))), ((int)(((byte)(59)))));
this.ucTrackBar1.LineWidth = 8F;
this.ucTrackBar1.Location = new System.Drawing.Point(68, 134);
this.ucTrackBar1.MaxValue = 255F;
this.ucTrackBar1.MinValue = 0F;
this.ucTrackBar1.Name = "ucTrackBar1";
this.ucTrackBar1.Size = new System.Drawing.Size(274, 20);
this.ucTrackBar1.TabIndex = 44;
this.ucTrackBar1.Text = "ucTrackBar1";
this.ucTrackBar1.Value1 = 0F;
this.ucTrackBar1.Value2 = 127F;
this.ucTrackBar1.Value3 = 255F;
this.ucTrackBar1.Value1Changed += new System.EventHandler(this.ucTrackBar1_Value1Changed);
this.ucTrackBar1.Value2Changed += new System.EventHandler(this.ucTrackBar1_Value2Changed);
this.ucTrackBar1.Value3Changed += new System.EventHandler(this.ucTrackBar1_Value3Changed);
//
// logButton
//
this.logButton.BackColor = System.Drawing.SystemColors.ControlDark;
this.logButton.BtnSelect = false;
this.logButton.BtnText = "log";
this.logButton.Location = new System.Drawing.Point(339, 43);
this.logButton.Name = "logButton";
this.logButton.Size = new System.Drawing.Size(41, 21);
this.logButton.TabIndex = 43;
this.logButton.Click += new System.EventHandler(this.logButton_Click);
//
// skipButton
//
this.skipButton.BackColor = System.Drawing.SystemColors.ControlDark;
this.skipButton.BtnSelect = false;
this.skipButton.BtnText = "skip";
this.skipButton.Location = new System.Drawing.Point(339, 74);
this.skipButton.Name = "skipButton";
this.skipButton.Size = new System.Drawing.Size(41, 21);
this.skipButton.TabIndex = 42;
this.skipButton.Click += new System.EventHandler(this.skipButton_Click);
//
// pictureBox1
//
this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox1.BackColor = System.Drawing.Color.White;
this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pictureBox1.Location = new System.Drawing.Point(76, 9);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(256, 124);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox1.TabIndex = 41;
this.pictureBox1.TabStop = false;
//
// DisplayCameraControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.label7);
this.Controls.Add(this.trackBar3);
this.Controls.Add(this.label6);
this.Controls.Add(this.trackBar2);
this.Controls.Add(this.label5);
this.Controls.Add(this.trackBar1);
this.Controls.Add(this.label4);
this.Controls.Add(this.numericUpDown1);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.button5);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.ucTrackBar1);
this.Controls.Add(this.logButton);
this.Controls.Add(this.skipButton);
this.Controls.Add(this.pictureBox1);
this.Name = "DisplayCameraControl";
this.Size = new System.Drawing.Size(490, 345);
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
public void OnTimerAutoExposure(object source, System.Timers.ElapsedEventArgs e)
{
double paramValue = m_camera.GetExposureTime();
decimal txtVale = 0;
int sec = 0;
int msec = 0;
int usec = 0;
m_camera.UpdateExposureTime(ref sec, ref msec, ref usec, (UInt64)(paramValue * 1000));
//UpdateExposureTime((UInt64)paramValue * 1000);
}
///
/// 最佳
///
public void BestButtonMethod()
{
OpenCvSharp.Point startIndex = this.getStartIndex(this.OldMat, oldHists, (float)numericUpDown1.Value);
//计算对比度
label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
//计算亮度
label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
this.scrollMethod();
updateHistogramRect(true);
}
///
/// 最大最小
///
public void MaxMinButtonMethod()
{
OpenCvSharp.Point startIndex = this.getStartIndex(this.OldMat, oldHists, 0);
//计算对比度
label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
//计算亮度
label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
//this.parentf
//this.scrollMethod();
updateHistogramRect(true);
}
///
/// 原始状态
///
public void OriginButtonMethod()
{
this.trackBar1.Value = -50;
this.trackBar2.Value = 100;
this.trackBar3.Value = 100;
label5.Text = (trackBar1.Value / 100.0).ToString("f2");
label6.Text = (trackBar2.Value / 100.0).ToString("f2");
label7.Text = (trackBar3.Value / 100.0).ToString("f2");
if (this.OldMat == null)
{
//MessageBox.Show("请打开图片");
return;
}
updateHistogramRect(true);
/**待处理**///this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.ResetBoxBitmap();
//this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(oldMat));
}
///
/// 伽马0.45
///
public void Gamma45ButtonMethod()
{
this.trackBar3.Value = 45;
label7.Text = (trackBar3.Value / 100.0).ToString("f2");
this.scrollMethod();
updateHistogramRect(true);
}
///
/// 最佳
/// 确定当前直方图中排除图像中包含的像素的1‰的值,
/// 并在屏幕上显示以此方式确定的灰度或颜色范围。
/// (您可以将1‰的值调整为适合您的需求。)
/// https://blog.csdn.net/qq_20095389/article/details/83658878
/// https://blog.csdn.net/lantishua/article/details/46377325
///
///
///
private void button2_Click(object sender, EventArgs e)
{
if (this.OldMat == null)
{
return;
}
this.BestButtonMethod();
}
///
/// 最大最小
///
///
///
private void button3_Click(object sender, EventArgs e)
{
if (this.OldMat == null)
{
return;
}
this.MaxMinButtonMethod();
}
///
/// 伽马0.45
/// 需要调整直线的弧度
/// 直方图曲线根据伽马值进行变化
///
///
///
private void button4_Click(object sender, EventArgs e)
{
if (this.OldMat == null)
{
return;
}
this.Gamma45ButtonMethod();
}
///
/// 原始状态
///
///
///
private void button5_Click(object sender, EventArgs e)
{
this.OriginButtonMethod();
}
///
/// skip按钮
/// 显示直方图时,忽略黑色的灰度或颜色值。
/// 这使您可以为背景为黑色的图像实现有意义的直方图显示。
///
///
///
private void skipButton_Click(object sender, EventArgs e)
{
if (this.OldMat == null)
{
return;
}
//设置按钮的选中/非选择的状态
skipButton.BtnSelect = !skipButton.BtnSelect;
//this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled = skipButton.BtnSelect;
updateHistImg(null);
}
///
/// log按钮
/// 以对数比例显示直方图
///
///
///
private void logButton_Click(object sender, EventArgs e)
{
if (this.OldMat == null)
{
return;
}
//设置按钮的选中/非选择的状态
logButton.BtnSelect = !logButton.BtnSelect;
//this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled = logButton.BtnSelect;
updateHistImg(null);
}
///
/// 最佳设置的数值改变
///
///
///
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
//this.AppWorkspace.ActiveDocumentWorkspace.HistogramPercent = (int)numericUpDown1.Value;
}
///
/// 亮度改变
///
///
///
private void trackBar1_Scroll(object sender, EventArgs e)
{
trackBar1Value = trackBar1.Value;
//this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramBeta = trackBar1.Value / 100.0;
label5.Text = (trackBar1.Value / 100.0).ToString("f2");
updateHistogramRect(true);
}
///
/// 亮度改变
///
///
///
private void label5_Changed(object sender, EventArgs e)
{
//this.AppWorkspace.ActiveDocumentWorkspace.HistogramBeta = double.Parse(label5.Text);
this.scrollMethod();
}
///
/// 对比度改变
///
///
///
private void trackBar2_Scroll(object sender, EventArgs e)
{
trackBar2Value = trackBar2.Value;
label6.Text = (trackBar2.Value / 100.0).ToString("f2");
updateHistogramRect(true);
}
///
/// 对比度改变
///
///
///
private void label6_Changed(object sender, EventArgs e)
{
//this.AppWorkspace.ActiveDocumentWorkspace.HistogramAlpha = double.Parse(label6.Text);
this.scrollMethod();
}
///
/// gamma改变
/// gamma值小于1时,会拉伸图像中灰度级较低的区域,同时会压缩灰度级较高的部分
/// gamma值大于1时,会拉伸图像中灰度级较高的区域,同时会压缩灰度级较低的部分
///
///
///
private void trackBar3_Scroll(object sender, EventArgs e)
{
trackBar3Value = trackBar3.Value;
label7.Text = (trackBar3.Value / 100.0).ToString("f2");
updateHistogramRect(true);
}
///
/// gamma改变
///
///
///
private void label7_Changed(object sender, EventArgs e)
{
//this.AppWorkspace.ActiveDocumentWorkspace.HistogramGamma = double.Parse(label7.Text);
this.scrollMethod();
}
///
/// 绘制直方图
///
///
///
private unsafe void updateHistImg(Mat[] hists)
{
if (this.OldMat == null)
{
return;
}
Mat[] mats = Cv2.Split(this.OldMat);//一张图片,将panda拆分成3个图片装进mat
Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
Mat[] mats1;
if (mats.Length < 2)
mats1 = new Mat[] { mats[0] };//panda的第二个通道,也就是G
else
mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
Mat[] mats2;
if (mats.Length < 3)
mats2 = new Mat[] { mats[0] };//panda的第三个通道,也就是R
else
mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
if (hists == null)
{
hists = new Mat[] { new Mat(), new Mat(), new Mat() };//一个矩阵数组,用来接收直方图,记得全部初始化
int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
int[] channels1 = new int[] { 0 };
int[] channels2 = new int[] { 0 };
int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats0, channels0, mask, hists[0], 1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats1, channels1, mask, hists[1], 1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats2, channels2, mask, hists[2], 1, histsize, range);//对被拆分的图片单独进行计算
if (logButton.BtnSelect)
{
//取对数
for (int j = 0; j < hists.Length; j++)
{
List ProbPixel = new List();
for (int i = 0; i < hists[j].Rows; i++)
{
if (((float*)hists[j].Ptr(0))[i] == 0)
{
((float*)hists[j].Ptr(0))[i] = ((float*)hists[j].Ptr(0))[i];
ProbPixel.Add(0);
}
else
{
((float*)hists[j].Ptr(0))[i] = (float)Math.Log10(((float*)hists[j].Ptr(0))[i]/* + 9*/);
ProbPixel.Add(1);
}
}
double max1jVal = 0;
double min1jVal = 0;
//找到直方图中的最大值和最小值
Cv2.MinMaxLoc(hists[j], out min1jVal, out max1jVal);
if (min1jVal >= max1jVal)
{
continue;
}
//归一化到0~255,并根据AxioVision添加偏置值
for (int i = 0; i < hists[j].Rows; i++)
{
((float*)hists[j].Ptr(0))[i] = (float)((((float*)hists[j].Ptr(0))[i] - 0) * 255.0 / (max1jVal - 0)) + (float)(min1jVal > 0 ? (ProbPixel[i] * min1jVal * 255.0 / max1jVal) : ProbPixel[i] * 5);
}
}
}
if (skipButton.BtnSelect)
{
//去掉黑色部分 和 白色部分
for (int j = 0; j < hists.Length; j++)
{
((float*)hists[j].Ptr(0))[0] = 0;
((float*)hists[j].Ptr(0))[255] = 0;
}
}
}
double max2Val = 0;
double max1Val = 0;
double max0Val = 0;
double minVal = 0;
//为了更好显示直方图细节,使用4倍尺寸绘制直方图
int histSize = hists[0].Rows * 4;
Mat histImg = new Mat(histSize, histSize, MatType.CV_8UC3, new Scalar(255, 255, 255));
//找到直方图中的最大值和最小值
Cv2.MinMaxLoc(hists[2], out minVal, out max2Val);
Cv2.MinMaxLoc(hists[1], out minVal, out max1Val);
Cv2.MinMaxLoc(hists[0], out minVal, out max0Val);
double maxVal = Math.Max(max2Val, Math.Max(max0Val, max1Val));
if (maxVal < 1)
return;
// 设置最大峰值为图像高度的90%
double hpt = 0.9 * histSize;
//灰度图的显示直方图较为简单,显示一个通道即可
if (isGray)
{
Mat hist = hists[0];
int lastY2 = histSize - 1;
for (int h = 0; h < hists[0].Rows; h++)
{
int intensity = (int)(hist.At(h) * hpt / maxVal);
int lastY1 = lastY2;
lastY2 = histSize - intensity - 1 - (hist.At(h) > 0 ? 4 : 0);
if (lastY2 < lastY1)
{
Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), new Scalar(0, 0, 0, 255), 2, LineTypes.Link4);
}
else
{
Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lastY1 + 2)), new Scalar(0, 0, 0, 255), 2, LineTypes.Link4);
}
}
}
//彩度图显示BGR三个通道的直方图
else
{
int lineWidth = 2;
for (int j = hists.Length - 1; j >= 0; j--)
{
Mat hist = hists[j];
int lastY2 = histSize - 1;
for (int h = 0; h < hists[0].Rows; h++)
{
int intensity = (int)(hist.At(h) * hpt / maxVal);
int lastY1 = lastY2;
lastY2 = histSize - intensity - 1 - (hist.At(h) > 0 ? 4 : 0);
if (h > 0)
{
//显示0.5位置的直方图,这样与AxioVision效果更加近似
int lasty12 = (lastY1 + lastY2) / 2;
if (lasty12 < lastY1)
{
Cv2.Line(histImg, new OpenCvSharp.Point(h * 4 - 2, lastY1), new OpenCvSharp.Point(h * 4 - 2, Math.Min(lasty12, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
}
else
{
Cv2.Line(histImg, new OpenCvSharp.Point(h * 4 - 2, lastY1), new OpenCvSharp.Point(h * 4 - 2, Math.Max(lasty12, lastY1 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
}
if (lastY2 < lasty12)
{
Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lasty12 - 2)), color[j], lineWidth, LineTypes.Link4);
}
else
{
Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lasty12 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
}
}
else
{
//灰度值为0的线的绘制
if (lastY2 < lastY1)
{
Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
}
else
{
Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Max(lastY2, lastY1 + 2)), color[j], lineWidth, LineTypes.Link4/*AntiAlias*/);
}
}
}
}
}
this.pictureBox1.BackgroundImage/*Image*/ = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
}
///
/// 测试曲线拟合的代码
///
private void testCurveFit()
{
//创建用于绘制的深蓝色背景图像
Mat image = new Mat(480, 640, MatType.CV_8UC3, new Scalar(0/*255*/, 0, 0, 255));// cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC3); image.setTo(cv::Scalar(100, 0, 0));
//输入拟合点
List points = new List();// std::vector points;
points.Add(new OpenCvSharp.Point(0, 254));
points.Add(new OpenCvSharp.Point(127, 222/*32*/));
points.Add(new OpenCvSharp.Point(254, 0));
//points.Add(new OpenCvSharp.Point(100, 58));
//points.Add(new OpenCvSharp.Point(150, 70));
//points.Add(new OpenCvSharp.Point(200, 90));
////points.push_back(cv::Point(100., 58.)); points.push_back(cv::Point(150., 70.)); points.push_back(cv::Point(200., 90.));
//points.Add(new OpenCvSharp.Point(252, 140));
//points.Add(new OpenCvSharp.Point(300, 220));
//points.Add(new OpenCvSharp.Point(350, 400));
//points.push_back(cv::Point(252., 140.)); points.push_back(cv::Point(300., 220.)); points.push_back(cv::Point(350., 400.));
List> pointsIn = new List>()
{
points
};
//将拟合点绘制到空白图上
for (int i = 0; i < points.Count; i++)
{
Cv2.Circle(image, points[i].X, points[i].Y, 5, new Scalar(0, 0, 255), 2, LineTypes.Link8, 0);
//cv::circle(image, points[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
}
//绘制折线
Cv2.Polylines(image, pointsIn/*(IEnumerable)(points.ToArray())*/, false, new Scalar(0, 255, 0), 1, LineTypes.Link8, 0); //cv::polylines(image, points, false, cv::Scalar(0, 255, 0), 1, 8, 0);
Mat A = new Mat(3 + 1/*480*/, 1/*640*/, MatType.CV_64FC1, new Scalar(0));// cv::Mat A;
polynomial_curve_fit(points.ToArray(), 3, A);
//std::cout << "A = " << A << std::endl;
List points_fitted = new List(); //std::vector points_fitted;
List dataFitted = new List();
dataFitted.Add(A.At(0, 0));
dataFitted.Add(A.At(1, 0));
dataFitted.Add(A.At(2, 0));
dataFitted.Add(A.At(3, 0));
for (int x = 0; x < 255; x++)
{
double y = A.At(0, 0) + A.At(1, 0) * x + A.At(2, 0) * Math.Pow(x, 2) + A.At(3, 0) * Math.Pow(x, 3);
// double y = A.at(0, 0) + A.at(1, 0) * x + A.at(2, 0)*std::pow(x, 2) + A.at(3, 0)*std::pow(x, 3);
points_fitted.Add(new OpenCvSharp.Point(x, y));
// points_fitted.push_back(cv::Point(x, y));
}
List> points_fittedIn = new List>()
{
points_fitted
};
//黄色线表示拟合后的曲线,成功
Cv2.Polylines(image, points_fittedIn, false, new Scalar(0, 255, 255), 1, LineTypes.Link8, 0); //cv::polylines(image, points_fitted, false, cv::Scalar(0, 255, 255), 1, 8, 0);
Cv2.ImShow("image", image);// cv::imshow("image", image);
//this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
}
///
/// 将拟合点绘制到空白图上
/// //原文链接:https://blog.csdn.net/guduruyu/article/details/72866144
///
/// 拟合点
/// 拟合矩阵的??数量
/// 空白图
///
private unsafe bool polynomial_curve_fit(OpenCvSharp.Point[] key_point, int n, Mat A)
{
//Number of key points
int N = key_point.Length;
//构造矩阵X
Mat X = new Mat(n + 1, n + 1, MatType.CV_64FC1, new Scalar(0));// cv::Mat X = cv::Mat::zeros(n + 1, n + 1, CV_64FC1);
for (int i = 0; i < n + 1; i++)
{
for (int j = 0; j < n + 1; j++)
{
((double*)X.Ptr(i))[j] = 0;//111
for (int k = 0; k < N; k++)
{
((double*)X.Ptr(i))[j] = X/*[i]*/.At(i, j) + (double)Math.Pow(key_point[k].X, i + j);// X.at(i, j) = X.at(i, j) + std::pow(key_point[k].x, i + j);
}
}
}
//构造矩阵Y
Mat Y = new Mat(n + 1, 1, MatType.CV_64FC1, new Scalar(0));// cv::Mat Y = cv::Mat::zeros(n + 1, 1, CV_64FC1);
for (int i = 0; i < n + 1; i++)
{
((double*)Y.Ptr(i))[0] = 0;//111
for (int k = 0; k < N; k++)
{
((double*)Y.Ptr(i))[0] = Y.At(i, 0) + (double)(Math.Pow(key_point[k].X, i) * key_point[k].Y);// Y.at(i, 0) = Y.at(i, 0) + std::pow(key_point[k].x, i) * key_point[k].y;
}
}
//A = new Mat(n + 1, 1, MatType.CV_64FC1, new Scalar(0));// A = cv::Mat::zeros(n + 1, 1, CV_64FC1);
//List dataFitted = new List();
//dataFitted.Add(Y.At(0, 0));
//dataFitted.Add(Y.At(1, 0));
//dataFitted.Add(Y.At(2, 0));
//dataFitted.Add(Y.At(3, 0));
//for (int i = 0; i < n + 1; i++)
//{
// for (int j = 0; j < n + 1; j++)
// {
// dataFitted.Add(X.At(i, j));
// }
//}
//求解矩阵A
Cv2.Solve(X, Y, A, DecompTypes.LU);//Cv2.Solve(X, Y, A, DecompTypes.LU); cv::solve(X, Y, A, cv::DECOMP_LU);
//dataFitted.Add(A.At(0, 0));
//dataFitted.Add(A.At(1, 0));
//dataFitted.Add(A.At(2, 0));
//dataFitted.Add(A.At(3, 0));
return true;
}
///
/// 通过颜色通道去除像素点的千分比计算有效阈值
///
///
///
///
private OpenCvSharp.Point getStartIndex(Mat mat, Mat[] hists, float percentValue)
{
//灰度化图片取第一通道
Mat histGray = hists[0];
//彩色图片取灰度化后的通道
if (!isGray)
{
OpenCvSharp.Point startIndex = new OpenCvSharp.Point(0, histGray.Rows);
//计算三次
OpenCvSharp.Point startIndex0 = this.getStartRange(mat, hists[0], percentValue);
OpenCvSharp.Point startIndex1 = this.getStartRange(mat, hists[1], percentValue);
OpenCvSharp.Point startIndex2 = this.getStartRange(mat, hists[2], percentValue);
startIndex.X = Math.Min(startIndex0.X, Math.Min(startIndex1.X, startIndex2.X));
startIndex.Y = Math.Max(startIndex0.Y, Math.Max(startIndex1.Y, startIndex2.Y));
startIndex.Y = Math.Min(255 - 1, startIndex.Y);
startIndex.X = Math.Max(startIndex.X, 1);
startIndex.Y = Math.Max(startIndex.X + 1, startIndex.Y);
return startIndex;
}
return this.getStartRange(mat, histGray, percentValue);
}
private OpenCvSharp.Point getStartRange(Mat mat, Mat histGray, float percentValue)
{
if (this.OldMat == null)
{
return new OpenCvSharp.Point(1, 254); ;
}
//计算灰度分布密度
float totalPoints = this.OldMat.Cols * this.OldMat.Rows;
OpenCvSharp.Point startIndex = new OpenCvSharp.Point(0, histGray.Rows);
bool foundStartTag = false;
bool foundEndTag = false;
//根据累计直方图分布计算左右阈值
float equalizeHists = 0;
for (int i = 0; i < histGray.Rows; ++i)
{
equalizeHists += ((float)(histGray.At(i) / (totalPoints * 1.0))) * 1000;
if (!foundStartTag && equalizeHists > percentValue)
{
foundStartTag = true;
startIndex.X = i;
}
else if (equalizeHists >= 1000 - percentValue)
{
foundEndTag = true;
startIndex.Y = i;
}
if (foundStartTag && foundEndTag)
break;
}
startIndex.Y = Math.Min(255 - 1, startIndex.Y);
startIndex.X = Math.Max(startIndex.X, 1);
startIndex.Y = Math.Max(startIndex.X + 1, startIndex.Y);
return startIndex;
}
///
/// 更新直方图特征曲线
///
/// 是否需要更新三个控制点的位置
private void updateHistogramRect(bool updateThreePoints)
{
//为了更好显示直方图细节,使用4倍尺寸绘制直方图
int histSize = 256/*oldHists[0].Rows*/ * 4;
//创建用于绘制的深蓝色背景图像
Mat image = new Mat(histSize, histSize, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
//输入拟合点
List points = new List();
//根据亮度和对比度计算左右阈值
int grayMin = (int)(0 - (256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) + double.Parse(label5.Text) * 510.0) / 2.0);
int grayMax = (int)((256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) - double.Parse(label5.Text) * 510.0) / 2.0);
if (grayMin >= grayMax)
{
return;
}
if (updateThreePoints)
{
ucTrackBar1.Value1 = grayMin;
ucTrackBar1.Value3 = grayMax;
//ucTrackBar1.Value2 = (float)((grayMin + grayMax) / 2.0);
}
//gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
double gamma = Math.Max(0.01, double.Parse(label7.Text));
//计算Value2
ucTrackBar1.Value2 = (float)Math.Max(grayMin, Math.Min(grayMax, Math.Pow(0.5, 1.0 / gamma) * (grayMax - grayMin) + grayMin));
ucTrackBar1.Refresh();
int lastY2 = histSize + 0;// histSize - 1;
for (int h = 0; h <= 256; h++)
{
if (h < grayMin)
{
points.Add(new OpenCvSharp.Point(h * 4, lastY2));
continue;
}
else if (h > grayMax)
{
lastY2 = -1;// 0;
points.Add(new OpenCvSharp.Point(h * 4, lastY2));
continue;
}
int lastY1 = (int)Math.Round((1.0 - Math.Pow((h - grayMin) * 1.0 / (grayMax - grayMin), gamma)) * (histSize + 1/*histSize - 1*/)) - 1;
lastY1 = Math.Min(lastY2, Math.Max(0, lastY1));
if (lastY2 == lastY1)
{
if (h == 0 || h == 256)
{
points.Add(new OpenCvSharp.Point(h * 4, lastY1));
}
}
else
{
points.Add(new OpenCvSharp.Point(h * 4, lastY1));
lastY2 = lastY1;
}
}
lastY2 = histSize + 0;// histSize - 1;
//将第一个点的位置设置最底部,保证曲线平滑性
//if (points[0].X > 4 && points[0].Y < lastY2)
//{
// points.Insert(0, new OpenCvSharp.Point(points[0].X - 4, lastY2));
//}
List> pointsIn = new List>()
{
points
};
//绘制折线
Cv2.Polylines(image, pointsIn/*(IEnumerable)(points.ToArray())*/, false, new Scalar(0, 0/*255*/, 0, 255), 4/*1*/, LineTypes.Link8, 0); //cv::polylines(image, points, false, cv::Scalar(0, 255, 0), 1, 8, 0);
//this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);
Mat A = new Mat(3 + 1, 1, MatType.CV_64FC1, new Scalar(0));
polynomial_curve_fit(points.ToArray(), 3, A);
List points_fitted = new List(); //std::vector points_fitted;
List dataFitted = new List();
dataFitted.Add(A.At(0, 0));
dataFitted.Add(A.At(1, 0));
dataFitted.Add(A.At(2, 0));
dataFitted.Add(A.At(3, 0));
for (int x = 0; x < histSize + 1; x++)
{
if (x < grayMin * 4)
{
points_fitted.Add(new OpenCvSharp.Point(x, lastY2));
continue;
}
else if (x > grayMax * 4)
{
lastY2 = -1;// 0;
points_fitted.Add(new OpenCvSharp.Point(x, lastY2));
continue;
}
double y = A.At(0, 0) + A.At(1, 0) * x + A.At(2, 0) * Math.Pow(x, 2) + A.At(3, 0) * Math.Pow(x, 3);
points_fitted.Add(new OpenCvSharp.Point(x, y));
}
//List> points_fittedIn = new List>()
//{
// points_fitted
//};
////绘制折线
//Cv2.Polylines(image, points_fittedIn/*(IEnumerable)(points.ToArray())*/, false, new Scalar(0, 255/*255*/, 0, 255), 4/*1*/, LineTypes.Link8, 0); //cv::polylines(image, points, false, cv::Scalar(0, 255, 0), 1, 8, 0);
this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);
// //黄色线表示拟合后的曲线,成功
// Cv2.Polylines(image, points_fittedIn, false, new Scalar(0, 255, 255), 1, LineTypes.Link8, 0); //cv::polylines(image, points_fitted, false, cv::Scalar(0, 255, 255), 1, 8, 0);
// Cv2.ImShow("image", image);// cv::imshow("image", image);
//this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
}
///
///
///
/// 原图
/// 亮度
/// 对比度
/// gamma值
///
public static Mat scrollMethod(Mat oldmat, string label5_Text, string label6_Text, string label7_Text)
{
if (oldmat == null)
{
return null;
}
Mat[] mats = Cv2.Split(oldmat);//一张图片,将panda拆分成3个图片装进mat
bool isGray = true;
///
/// 一个矩阵数组,用来接收直方图,记得全部初始化
///
Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };
Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
Mat[] mats1;
if (mats.Length < 2)
mats1 = new Mat[] { mats[0] };//panda的第二个通道,也就是G
else
mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
Mat[] mats2;
if (mats.Length < 3)
{
mats2 = new Mat[] { mats[0] };//panda的第三个通道,也就是R
mats = new Mat[] { mats0[0], mats0[0], mats0[0] };
}
else
mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
int[] channels1 = new int[] { 0 };
int[] channels2 = new int[] { 0 };
int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
for (int h = 0; h < oldHists[0].Rows; h++)
{
for (int j = oldHists.Length - 1; j >= 1; j--)
{
if (oldHists[j].At(h) != oldHists[0].At(h))
{
isGray = false;
break;
}
}
if (!isGray)
break;
}
//根据亮度和对比度计算左右阈值
int grayMin = (int)(0 - (256.0 / (double.Parse(label6_Text) == 0 ? 0.01 : double.Parse(label6_Text)) + double.Parse(label5_Text) * 510.0) / 2.0);
int grayMax = (int)((256.0 / (double.Parse(label6_Text) == 0 ? 0.01 : double.Parse(label6_Text)) - double.Parse(label5_Text) * 510.0) / 2.0);
if (grayMin >= grayMax)
{
return null;
}
Mat dst = new Mat();
//如果是灰度化图片,则只需计算一个通道。对灰度值进行映射,BGR根据左右阈值做缩放操作
if (isGray)
{
Cv2.Min(mats[0], new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMax)), dst);
Cv2.Max(dst, new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMin)), dst);
Cv2.Normalize(dst, dst, 0, 255, NormTypes.MinMax);
}
else
{
if (mats.Length < oldHists.Length)
for (int j = 0; j < oldHists.Length; j++)
{
Cv2.Min(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMax)), mats[j]);
Cv2.Max(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMin)), mats[j]);
Cv2.Normalize(mats[j], mats[j], 0, 255, NormTypes.MinMax);
}
else
for (int j = 0; j < oldHists.Length; j++)
{
Cv2.Min(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMax)), mats[j]);
Cv2.Max(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMin)), mats[j]);
Cv2.Normalize(mats[j], mats[j], 0, 255, NormTypes.MinMax);
}
Cv2.Merge(mats, dst);
}
//灰度归一化
dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
//gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7_Text)), dst);
dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
//Document document = Document.FromImage(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
//this.AppWorkspace.ActiveDocumentWorkspace.setDoc(document, false);
//this.AppWorkspace.ActiveDocumentWorkspace.Refresh();
////this.AppWorkspace.ActiveDocumentWorkspace.CompositionSurface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
#region 均衡化的方法备份
////对灰度值进行映射(均衡化)
//float[] totalPoints = new float[] { oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows };
////去掉黑色部分 和 白色部分
//for (int j = 0; j < oldHists.Length; j++)
//{
// for (int i = 0; i < grayMin; i++)
// {
// totalPoints[j] = totalPoints[j] - oldHists[j].At(i);
// }
// for (int i = grayMax; i < oldHists[j].Rows; i++)
// {
// totalPoints[j] = totalPoints[j] - oldHists[j].At(i);
// }
//}
//for (int j = 0; j < (isGray ? 1 : oldHists.Length); j++)
//{
// //计算灰度分布密度
// //List ProbPixel = new List();
// //计算累计直方图分布
// List equalizeHists = new List();
// Mat hist = oldHists[j];
// //计算累计直方图分布
// for (int i = 0; i < hist.Rows; ++i)
// {
// //去掉黑色部分 和 白色部分
// if (i < grayMin || i > grayMax)
// {
// if (i == 0)
// {
// equalizeHists.Add(0);
// }
// else
// {
// equalizeHists.Add(equalizeHists[i - 1]);
// }
// }
// else if (i == 0)
// {
// equalizeHists.Add((float)(hist.At(i) / (totalPoints[j] * 1.0)));
// }
// else
// {
// equalizeHists.Add(equalizeHists[i - 1] + (float)(hist.At(i) / (totalPoints[j] * 1.0)));
// }
// }
// //累计分布取整
// for (int i = 0; i < equalizeHists.Count; ++i)
// {
// float numHist = equalizeHists[i];
// equalizeHists[i] = Math.Min(255, (int)(numHist * 255.0 + 0.5));
// }
// for (int y = 0; y < h; ++y)
// //对灰度值进行映射,BGR根据左右阈值做缩放操作
// {
// byte* imageData = (byte*)(mats[j].Ptr(y));
// //对灰度值进行映射
// for (int x = 0; x < w; ++x)
// {
// int oldvalue = imageData[x];
// if (oldvalue < grayMin)
// {
// imageData[x] = 0;
// }
// else if (oldvalue > grayMax)
// {
// imageData[x] = 255;
// }
// else
// {
// imageData[x] = (byte)equalizeHists[oldvalue];
// }
// }
// }
//}
//Mat dst = new Mat();
////灰度归一化
//if (isGray)
//{
// mats[0].ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
//}
//else
//{
// Cv2.Merge(mats, dst);
// dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
//}
////gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
//Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7.Text)), dst);
//dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
//this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
#endregion
return dst;
}
///
/// 根据亮度、对比度、gamma对图片进行处理
///
private void scrollMethod()
{
trackBar1Value = trackBar1.Value;
trackBar2Value = trackBar2.Value;
trackBar3Value = trackBar3.Value;
//if (this.OldMat == null)
//{
// return;
//}
//Mat[] mats = Cv2.Split(this.OldMat);//一张图片,将panda拆分成3个图片装进mat
////根据亮度和对比度计算左右阈值
//int grayMin = (int)(0 - (256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) + double.Parse(label5.Text) * 510.0) / 2.0);
//int grayMax = (int)((256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) - double.Parse(label5.Text) * 510.0) / 2.0);
//if (grayMin >= grayMax)
//{
// return;
//}
//Mat dst = new Mat();
////如果是灰度化图片,则只需计算一个通道。对灰度值进行映射,BGR根据左右阈值做缩放操作
//if (isGray)
//{
// Cv2.Min(mats[0], new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMax)), dst);
// Cv2.Max(dst, new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMin)), dst);
// Cv2.Normalize(dst, dst, 0, 255, NormTypes.MinMax);
//}
//else
//{
// for (int j = 0; j < oldHists.Length; j++)
// {
// Cv2.Min(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMax)), mats[j]);
// Cv2.Max(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMin)), mats[j]);
// Cv2.Normalize(mats[j], mats[j], 0, 255, NormTypes.MinMax);
// }
// Cv2.Merge(mats, dst);
//}
////灰度归一化
//dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
////gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
//Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7.Text)), dst);
//dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
//Document document = Document.FromImage(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
//this.AppWorkspace.ActiveDocumentWorkspace.setDoc(document, false);
//this.AppWorkspace.ActiveDocumentWorkspace.Refresh();
////this.AppWorkspace.ActiveDocumentWorkspace.CompositionSurface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
#region 均衡化的方法备份
////对灰度值进行映射(均衡化)
//float[] totalPoints = new float[] { oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows };
////去掉黑色部分 和 白色部分
//for (int j = 0; j < oldHists.Length; j++)
//{
// for (int i = 0; i < grayMin; i++)
// {
// totalPoints[j] = totalPoints[j] - oldHists[j].At(i);
// }
// for (int i = grayMax; i < oldHists[j].Rows; i++)
// {
// totalPoints[j] = totalPoints[j] - oldHists[j].At(i);
// }
//}
//for (int j = 0; j < (isGray ? 1 : oldHists.Length); j++)
//{
// //计算灰度分布密度
// //List ProbPixel = new List();
// //计算累计直方图分布
// List equalizeHists = new List();
// Mat hist = oldHists[j];
// //计算累计直方图分布
// for (int i = 0; i < hist.Rows; ++i)
// {
// //去掉黑色部分 和 白色部分
// if (i < grayMin || i > grayMax)
// {
// if (i == 0)
// {
// equalizeHists.Add(0);
// }
// else
// {
// equalizeHists.Add(equalizeHists[i - 1]);
// }
// }
// else if (i == 0)
// {
// equalizeHists.Add((float)(hist.At(i) / (totalPoints[j] * 1.0)));
// }
// else
// {
// equalizeHists.Add(equalizeHists[i - 1] + (float)(hist.At(i) / (totalPoints[j] * 1.0)));
// }
// }
// //累计分布取整
// for (int i = 0; i < equalizeHists.Count; ++i)
// {
// float numHist = equalizeHists[i];
// equalizeHists[i] = Math.Min(255, (int)(numHist * 255.0 + 0.5));
// }
// for (int y = 0; y < h; ++y)
// //对灰度值进行映射,BGR根据左右阈值做缩放操作
// {
// byte* imageData = (byte*)(mats[j].Ptr(y));
// //对灰度值进行映射
// for (int x = 0; x < w; ++x)
// {
// int oldvalue = imageData[x];
// if (oldvalue < grayMin)
// {
// imageData[x] = 0;
// }
// else if (oldvalue > grayMax)
// {
// imageData[x] = 255;
// }
// else
// {
// imageData[x] = (byte)equalizeHists[oldvalue];
// }
// }
// }
//}
//Mat dst = new Mat();
////灰度归一化
//if (isGray)
//{
// mats[0].ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
//}
//else
//{
// Cv2.Merge(mats, dst);
// dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
//}
////gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
//Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7.Text)), dst);
//dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
//this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
#endregion
}
///
/// 拖动左侧三角形
///
///
///
private void ucTrackBar1_Value1Changed(object sender, EventArgs e)
{
OpenCvSharp.Point startIndex = new OpenCvSharp.Point(ucTrackBar1.Value1, ucTrackBar1.Value3);
//计算对比度
label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
//计算亮度
label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
//备注:这里是可以优化用户体验的地方(避免操作事件引起多次计算发生)
//this.scrollMethod();
updateHistogramRect(false);
}
///
/// 拖动中间三角形
///
///
///
private void ucTrackBar1_Value2Changed(object sender, EventArgs e)
{
//计算gamma值
double gamma = 1.0 / Math.Log((ucTrackBar1.Value2 - ucTrackBar1.Value1) / (ucTrackBar1.Value3 - ucTrackBar1.Value1), 0.5);
gamma = Math.Max(0.01, gamma);
this.trackBar3.Value = Math.Min(299, (int)(gamma * 100));//备注:需要与AxioVision进行比较效果,调试一致
label7.Text = gamma.ToString("f2");
//备注:这里是可以优化用户体验的地方(避免操作事件引起多次计算发生)
updateHistogramRect(false);
}
///
/// 拖动右侧三角形
///
///
///
private void ucTrackBar1_Value3Changed(object sender, EventArgs e)
{
OpenCvSharp.Point startIndex = new OpenCvSharp.Point(ucTrackBar1.Value1, ucTrackBar1.Value3);// this.getStartIndex(oldMat, oldHists, (float)numericUpDown1.Value);
//计算对比度
label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
//计算亮度
label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
//this.scrollMethod();
updateHistogramRect(false);
}
}
}