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); } } }