| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498 | using OpenCvSharp;using PaintDotNet.CustomControl;using System;using System.Collections.Generic;using System.Windows.Forms;namespace PaintDotNet.Instrument{    /// <summary>    /// 工具-直方图    /// </summary>    internal class HistogramDialog : FloatingToolForm    {        #region 初始化变量        private AppWorkspace AppWorkspace;        /// <summary>        /// 一个矩阵数组,用来接收直方图,记得全部初始化        /// </summary>        Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };        /// <summary>        /// 灰度图        /// </summary>        private bool isGray = true;        /// <summary>        /// BGR线条颜色        /// </summary>        private Scalar[] color = new Scalar[] { new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255), new Scalar(0, 0, 255, 255) };        #endregion        #region 控件相关        private Button button2;        private Button button3;        private Button button4;        private Button button5;        private Label label1;        private Label label2;        private Label label3;        private NumericUpDown numericUpDown1;        private Label label4;        private CustomControl.TriangleTrackBar trackBar1;        private Label label5;        private Label label6;        private CustomControl.TriangleTrackBar trackBar2;        private Label label7;        private CustomControl.TriangleTrackBar trackBar3;        private CustomControl.SelectButton skipButton;        private CustomControl.SelectButton logButton;        private CustomControl.UCTrackBar ucTrackBar1;        private PictureBox pictureBox1;        private void InitializeLanguageText()        {            this.button2.Text = PdnResources.GetString("Menu.optimal.text");            this.button4.Text = PdnResources.GetString("Menu.Gammavalue.text") + "0.45";            this.button5.Text = PdnResources.GetString("Menu.Originalstate.text");            this.label1.Text = PdnResources.GetString("Menu.luminance.text") + ":";            this.label2.Text = PdnResources.GetString("Menu.Contrast.text") + ":";            this.label3.Text = PdnResources.GetString("Menu.Gammavalue.text") + ":";        }        private void InitializeComponent()        {            this.pictureBox1 = new System.Windows.Forms.PictureBox();            this.button2 = new System.Windows.Forms.Button();            this.button3 = new System.Windows.Forms.Button();            this.button4 = new System.Windows.Forms.Button();            this.button5 = new System.Windows.Forms.Button();            this.label1 = new System.Windows.Forms.Label();            this.label2 = new System.Windows.Forms.Label();            this.label3 = new System.Windows.Forms.Label();            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();            this.label4 = new System.Windows.Forms.Label();            this.trackBar1 = new PaintDotNet.CustomControl.TriangleTrackBar();            this.label5 = new System.Windows.Forms.Label();            this.label6 = new System.Windows.Forms.Label();            this.trackBar2 = new PaintDotNet.CustomControl.TriangleTrackBar();            this.label7 = new System.Windows.Forms.Label();            this.trackBar3 = new PaintDotNet.CustomControl.TriangleTrackBar();            this.skipButton = new PaintDotNet.CustomControl.SelectButton();            this.logButton = new PaintDotNet.CustomControl.SelectButton();            this.ucTrackBar1 = new PaintDotNet.CustomControl.UCTrackBar();            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();            this.SuspendLayout();            //             // 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.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;            this.pictureBox1.Location = new System.Drawing.Point(12, 12);            this.pictureBox1.Name = "pictureBox1";            this.pictureBox1.Size = new System.Drawing.Size(256, 124);            this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;            this.pictureBox1.TabIndex = 1;            this.pictureBox1.TabStop = false;            //             // 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(126, 274);            this.button2.Name = "button2";            this.button2.Size = new System.Drawing.Size(75, 23);            this.button2.TabIndex = 4;            this.button2.Text = "最佳";            this.button2.UseVisualStyleBackColor = true;            this.button2.Click += new System.EventHandler(this.button2_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(241, 303);            this.button3.Name = "button3";            this.button3.Size = new System.Drawing.Size(75, 23);            this.button3.TabIndex = 5;            this.button3.Text = "MIN/MAX";            this.button3.UseVisualStyleBackColor = true;            this.button3.Click += new System.EventHandler(this.button3_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(12, 303);            this.button4.Name = "button4";            this.button4.Size = new System.Drawing.Size(75, 23);            this.button4.TabIndex = 6;            this.button4.Text = "伽马值0.45";            this.button4.UseVisualStyleBackColor = true;            this.button4.Click += new System.EventHandler(this.button4_Click);            //             // 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(126, 303);            this.button5.Name = "button5";            this.button5.Size = new System.Drawing.Size(75, 23);            this.button5.TabIndex = 7;            this.button5.Text = "原始状态";            this.button5.UseVisualStyleBackColor = true;            this.button5.Click += new System.EventHandler(this.button5_Click);            //             // label1            //             this.label1.AutoSize = true;            this.label1.Location = new System.Drawing.Point(25, 166);            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 = 9;            this.label1.Text = "亮度:";            //             // label2            //             this.label2.AutoSize = true;            this.label2.Location = new System.Drawing.Point(13, 202);            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 = 10;            this.label2.Text = "对比度:";            //             // label3            //             this.label3.AutoSize = true;            this.label3.Location = new System.Drawing.Point(13, 238);            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 = 11;            this.label3.Text = "伽马值:";            //             // numericUpDown1            //             this.numericUpDown1.Location = new System.Drawing.Point(242, 276);            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 = 12;            this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;            this.numericUpDown1.Value = new decimal(new int[] {            200,            0,            0,            0});            this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);            //             // label4            //             this.label4.AutoSize = true;            this.label4.Location = new System.Drawing.Point(296, 280);            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 = 13;            this.label4.Text = "‰";            //             // trackBar1            //             this.trackBar1.Location = new System.Drawing.Point(67, 159);            this.trackBar1.Maximum = 200;            this.trackBar1.Minimum = -200;            this.trackBar1.Name = "trackBar1";            this.trackBar1.Size = new System.Drawing.Size(200, 30);            this.trackBar1.TabIndex = 14;            this.trackBar1.Value = -50;            this.trackBar1.TrackBarScroll += new System.EventHandler(this.trackBar1_Scroll);            //             // label5            //             this.label5.AutoSize = true;            this.label5.Location = new System.Drawing.Point(272, 166);            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 = 15;            this.label5.Text = "-0.5";            this.label5.TextChanged += new System.EventHandler(this.label5_Changed);            //             // label6            //             this.label6.AutoSize = true;            this.label6.Location = new System.Drawing.Point(272, 202);            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 = 17;            this.label6.Text = "1.00";            this.label6.TextChanged += new System.EventHandler(this.label6_Changed);            //             // trackBar2            //             this.trackBar2.Location = new System.Drawing.Point(67, 195);            this.trackBar2.Maximum = 999;            this.trackBar2.Minimum = 0;            this.trackBar2.Name = "trackBar2";            this.trackBar2.Size = new System.Drawing.Size(200, 30);            this.trackBar2.TabIndex = 16;            this.trackBar2.Value = 100;            this.trackBar2.TrackBarScroll += new System.EventHandler(this.trackBar2_Scroll);            //             // label7            //             this.label7.AutoSize = true;            this.label7.Location = new System.Drawing.Point(272, 238);            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 = 19;            this.label7.Text = "1.00";            this.label7.TextChanged += new System.EventHandler(this.label7_Changed);            //             // trackBar3            //             this.trackBar3.Location = new System.Drawing.Point(67, 230);            this.trackBar3.Maximum = 299;            this.trackBar3.Minimum = 0;            this.trackBar3.Name = "trackBar3";            this.trackBar3.Size = new System.Drawing.Size(200, 30);            this.trackBar3.TabIndex = 18;            this.trackBar3.Value = 100;            this.trackBar3.TrackBarScroll += new System.EventHandler(this.trackBar3_Scroll);            //             // skipButton            //             this.skipButton.BackColor = System.Drawing.SystemColors.ControlDark;            this.skipButton.BtnSelect = false;            this.skipButton.BtnText = "skip";            this.skipButton.Location = new System.Drawing.Point(275, 77);            this.skipButton.Name = "skipButton";            this.skipButton.Size = new System.Drawing.Size(41, 21);            this.skipButton.TabIndex = 20;            this.skipButton.Click += new System.EventHandler(this.skipButton_Click);            //             // logButton            //             this.logButton.BackColor = System.Drawing.SystemColors.ControlDark;            this.logButton.BtnSelect = false;            this.logButton.BtnText = "log";            this.logButton.Location = new System.Drawing.Point(275, 46);            this.logButton.Name = "logButton";            this.logButton.Size = new System.Drawing.Size(41, 21);            this.logButton.TabIndex = 21;            this.logButton.Click += new System.EventHandler(this.logButton_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(4, 139);            this.ucTrackBar1.MaxValue = 255F;            this.ucTrackBar1.MinValue = 0F;            this.ucTrackBar1.Name = "ucTrackBar1";            this.ucTrackBar1.Size = new System.Drawing.Size(274, 20);            this.ucTrackBar1.TabIndex = 22;            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);            //             // HistogramDialog            //             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;            this.ClientSize = new System.Drawing.Size(325, 338);            this.Controls.Add(this.ucTrackBar1);            this.Controls.Add(this.logButton);            this.Controls.Add(this.skipButton);            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.pictureBox1);            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;            this.Margin = new System.Windows.Forms.Padding(6);            this.Name = "HistogramDialog";            this.Text = "直方图";            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.HistogramDialog_FormClosing);            this.Controls.SetChildIndex(this.pictureBox1, 0);            this.Controls.SetChildIndex(this.button2, 0);            this.Controls.SetChildIndex(this.button3, 0);            this.Controls.SetChildIndex(this.button4, 0);            this.Controls.SetChildIndex(this.button5, 0);            this.Controls.SetChildIndex(this.label1, 0);            this.Controls.SetChildIndex(this.label2, 0);            this.Controls.SetChildIndex(this.label3, 0);            this.Controls.SetChildIndex(this.numericUpDown1, 0);            this.Controls.SetChildIndex(this.label4, 0);            this.Controls.SetChildIndex(this.trackBar1, 0);            this.Controls.SetChildIndex(this.label5, 0);            this.Controls.SetChildIndex(this.trackBar2, 0);            this.Controls.SetChildIndex(this.label6, 0);            this.Controls.SetChildIndex(this.trackBar3, 0);            this.Controls.SetChildIndex(this.label7, 0);            this.Controls.SetChildIndex(this.skipButton, 0);            this.Controls.SetChildIndex(this.logButton, 0);            this.Controls.SetChildIndex(this.ucTrackBar1, 0);            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();            this.ResumeLayout(false);            this.PerformLayout();        }        #endregion        public HistogramDialog(AppWorkspace AppWorkspace)        {            this.AppWorkspace = AppWorkspace;            InitializeComponent();            InitializeLanguageText();            this.Text = PdnResources.GetString("Menu.Tools.Histogram.Text");/*;//待修改中文资源-scc备注 20200108*/            if (this.AppWorkspace.ActiveDocumentWorkspace != null)            {                Mat[] mats = Cv2.Split(this.AppWorkspace.ActiveDocumentWorkspace.BoxMat);//一张图片,将panda拆分成3个图片装进mat                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<float>(h) != oldHists[0].At<float>(h))                        {                            isGray = false;                            break;                        }                    }                    if (!isGray)                        break;                }                updateHistImg(oldHists);                updateHistogramRect(false);                ////根据亮度和对比度计算左右阈值                //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;                //}                //ucTrackBar1.Value1 = grayMin;                //ucTrackBar1.Value3 = grayMax;                //ucTrackBar1.Value2 = (float)((grayMin + grayMax) / 2.0);            }            if(this.AppWorkspace != null)                this.AppWorkspace.ActiveDocumentWorkspaceChanged += new EventHandler(ButtonFocus);//切换窗口            //if (this.AppWorkspace.ActiveDocumentWorkspace != null)            //{            //    this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramBeta = -0.5;            //    this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramAlpha = 1.00;            //    this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramGamma = 1.00;            //    this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramPercent = 200;            //    this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramSkipEnabled = false;            //    this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramLogEnabled = false;            //}        }        /// <summary>        /// 更改按钮焦点        /// </summary>        /// <param name="dis">按钮区分</param>        public void ButtonFocus(object sender, EventArgs e)        {            if(AppWorkspace != null && AppWorkspace.ActiveDocumentWorkspace != null)            {                // 最佳                if (AppWorkspace.ActiveDocumentWorkspace.buttonType == 0)                {                    this.button2.Focus();                }                // 最大最小                if (AppWorkspace.ActiveDocumentWorkspace.buttonType == 1)                {                    this.button3.Focus();                }                // 伽马45                if (AppWorkspace.ActiveDocumentWorkspace.buttonType == 2)                {                    this.button4.Focus();                }                // 原始                if (AppWorkspace.ActiveDocumentWorkspace.buttonType == 3)                {                    this.button5.Focus();                }            }        }        /// <summary>        /// 最佳        /// </summary>        public void BestButtonMethod()        {            OpenCvSharp.Point startIndex = this.getStartIndex(this.AppWorkspace.ActiveDocumentWorkspace.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);        }        /// <summary>        /// 最大最小        /// </summary>        public void MaxMinButtonMethod()        {            OpenCvSharp.Point startIndex = this.getStartIndex(this.AppWorkspace.ActiveDocumentWorkspace.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.scrollMethod();            updateHistogramRect(true);        }        /// <summary>        /// 原始状态        /// </summary>        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.AppWorkspace.ActiveDocumentWorkspace == null)            {                MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));                return;            }            this.scrollMethod();            updateHistogramRect(true);            /**待处理**///this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.ResetBoxBitmap();            //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(oldMat));        }        /// <summary>        /// 伽马0.45        /// </summary>        public void Gamma45ButtonMethod()        {            this.trackBar3.Value = 45;            label7.Text = (trackBar3.Value / 100.0).ToString("f2");            this.scrollMethod();            updateHistogramRect(true);        }        /// <summary>        /// 重置Mat        /// </summary>        public void ResetMat()        {            if (this.AppWorkspace.ActiveDocumentWorkspace == null                || this.AppWorkspace.ActiveDocumentWorkspace.OldMat==null)            {                this.Visible = false;                isGray = true;//#18235                //updateHistImg(oldHists);                //updateHistogramRect(true);                return;            }            isGray = true;            Mat[] mats = Cv2.Split(this.AppWorkspace.ActiveDocumentWorkspace.OldMat);//一张图片,将panda拆分成3个图片装进mat            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<float>(h) != oldHists[0].At<float>(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);        }        /// <summary>        /// 最佳        /// 确定当前直方图中排除图像中包含的像素的1‰的值,        /// 并在屏幕上显示以此方式确定的灰度或颜色范围。         /// (您可以将1‰的值调整为适合您的需求。)        /// https://blog.csdn.net/qq_20095389/article/details/83658878        /// https://blog.csdn.net/lantishua/article/details/46377325        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void button2_Click(object sender, EventArgs e)        {            if (this.AppWorkspace.ActiveDocumentWorkspace == null)            {                MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));                return;            }            this.BestButtonMethod();            this.AppWorkspace.MaxMinBest(true, false, false, false);        }        /// <summary>        /// 最大最小        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void button3_Click(object sender, EventArgs e)        {            if (this.AppWorkspace.ActiveDocumentWorkspace == null)            {                MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));                return;            }            this.MaxMinButtonMethod();            this.AppWorkspace.MaxMinBest(false, true, false, false);        }        /// <summary>        /// 伽马0.45        /// 需要调整直线的弧度        /// 直方图曲线根据伽马值进行变化        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void button4_Click(object sender, EventArgs e)        {            if (this.AppWorkspace.ActiveDocumentWorkspace == null)            {                MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));                return;            }            this.Gamma45ButtonMethod();            this.AppWorkspace.MaxMinBest(false, false, false, true);        }        /// <summary>        /// 原始状态        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void button5_Click(object sender, EventArgs e)        {            this.OriginButtonMethod();            this.AppWorkspace.MaxMinBest(false, false, true, false);        }        /// <summary>        /// skip按钮        /// 显示直方图时,忽略黑色的灰度或颜色值。         /// 这使您可以为背景为黑色的图像实现有意义的直方图显示。        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void skipButton_Click(object sender, EventArgs e)        {            if (this.AppWorkspace.ActiveDocumentWorkspace == null)            {                MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));                return;            }            //设置按钮的选中/非选择的状态            skipButton.BtnSelect = !skipButton.BtnSelect;            this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled = skipButton.BtnSelect;            updateHistImg(null);        }        /// <summary>        /// log按钮        /// 以对数比例显示直方图        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void logButton_Click(object sender, EventArgs e)        {            if (this.AppWorkspace.ActiveDocumentWorkspace == null)            {                MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));                return;            }            //设置按钮的选中/非选择的状态            logButton.BtnSelect = !logButton.BtnSelect;            this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled = logButton.BtnSelect;            updateHistImg(null);        }        /// <summary>        /// 最佳设置的数值改变        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void numericUpDown1_ValueChanged(object sender, EventArgs e)        {            if(this.AppWorkspace.ActiveDocumentWorkspace!=null)                this.AppWorkspace.ActiveDocumentWorkspace.HistogramPercent = (int)numericUpDown1.Value;        }        /// <summary>        /// 亮度改变        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void trackBar1_Scroll(object sender, EventArgs e)        {            //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramBeta = trackBar1.Value / 100.0;            label5.Text = (trackBar1.Value / 100.0).ToString("f2");            this.scrollMethod();            updateHistogramRect(true);        }        /// <summary>        /// 亮度改变        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void label5_Changed(object sender, EventArgs e)        {            if(this.AppWorkspace.ActiveDocumentWorkspace!=null)            {                this.AppWorkspace.ActiveDocumentWorkspace.HistogramBeta = double.Parse(label5.Text);                //this.scrollMethod();            }        }        /// <summary>        /// 对比度改变        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void trackBar2_Scroll(object sender, EventArgs e)        {            label6.Text = (trackBar2.Value / 100.0).ToString("f2");            this.scrollMethod();             updateHistogramRect(true);        }        /// <summary>        /// 对比度改变        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void label6_Changed(object sender, EventArgs e)        {            if (this.AppWorkspace.ActiveDocumentWorkspace != null)            {                this.AppWorkspace.ActiveDocumentWorkspace.HistogramAlpha = double.Parse(label6.Text);                //this.scrollMethod();            }         }        /// <summary>        /// gamma改变        /// gamma值小于1时,会拉伸图像中灰度级较低的区域,同时会压缩灰度级较高的部分        /// gamma值大于1时,会拉伸图像中灰度级较高的区域,同时会压缩灰度级较低的部分        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void trackBar3_Scroll(object sender, EventArgs e)        {            label7.Text = (trackBar3.Value / 100.0).ToString("f2");            this.scrollMethod();            updateHistogramRect(true);        }        /// <summary>        /// gamma改变        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void label7_Changed(object sender, EventArgs e)        {            this.AppWorkspace.ActiveDocumentWorkspace.HistogramGamma = double.Parse(label7.Text);            //this.scrollMethod();        }        /// <summary>        /// 绘制直方图        /// </summary>        /// <param name="hist"></param>        /// <returns></returns>        private unsafe void updateHistImg(Mat[] hists)        {            if (this.AppWorkspace.ActiveDocumentWorkspace == null                || this.AppWorkspace.ActiveDocumentWorkspace.OldMat==null)            {                return;            }            Mat[] mats = Cv2.Split(this.AppWorkspace.ActiveDocumentWorkspace.OldMat);//一张图片,将panda拆分成3个图片装进mat            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 (logButton.BtnSelect)                {                    //取对数                    for (int j = 0; j < hists.Length; j++)                    {                        List<float> ProbPixel = new List<float>();                        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<float>(h) * hpt / maxVal);                    int lastY1 = lastY2;                    lastY2 = histSize - intensity - 1 - (hist.At<float>(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<float>(h) * hpt / maxVal);                        int lastY1 = lastY2;                        lastY2 = histSize - intensity - 1 - (hist.At<float>(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);        }        /// <summary>        /// 测试曲线拟合的代码        /// </summary>        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<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();// std::vector<cv::Point> 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<List<OpenCvSharp.Point>> pointsIn = new List<List<OpenCvSharp.Point>>()            {                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<OpenCvSharp.Point>)(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<OpenCvSharp.Point> points_fitted = new List<OpenCvSharp.Point>(); //std::vector<cv::Point> points_fitted;            List<double> dataFitted = new List<double>();            dataFitted.Add(A.At<double>(0, 0));            dataFitted.Add(A.At<double>(1, 0));            dataFitted.Add(A.At<double>(2, 0));            dataFitted.Add(A.At<double>(3, 0));            for (int x = 0; x < 255; x++)            {                double y = A.At<double>(0, 0) + A.At<double>(1, 0) * x + A.At<double>(2, 0) * Math.Pow(x, 2) + A.At<double>(3, 0) * Math.Pow(x, 3);                //    double y = A.at<double>(0, 0) + A.at<double>(1, 0) * x + A.at<double>(2, 0)*std::pow(x, 2) + A.at<double>(3, 0)*std::pow(x, 3);                points_fitted.Add(new OpenCvSharp.Point(x, y));                //    points_fitted.push_back(cv::Point(x, y));            }            List<List<OpenCvSharp.Point>> points_fittedIn = new List<List<OpenCvSharp.Point>>()            {                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);        }        /// <summary>        /// 将拟合点绘制到空白图上        /// //原文链接:https://blog.csdn.net/guduruyu/article/details/72866144        /// </summary>        /// <param name="key_point">拟合点</param>        /// <param name="n">拟合矩阵的??数量</param>        /// <param name="A">空白图</param>        /// <returns></returns>        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<double>(i, j) + (double)Math.Pow(key_point[k].X, i + j);// X.at<double>(i, j) = X.at<double>(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<double>(i, 0) + (double)(Math.Pow(key_point[k].X, i) * key_point[k].Y);// Y.at<double>(i, 0) = Y.at<double>(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<double> dataFitted = new List<double>();            //dataFitted.Add(Y.At<double>(0, 0));            //dataFitted.Add(Y.At<double>(1, 0));            //dataFitted.Add(Y.At<double>(2, 0));            //dataFitted.Add(Y.At<double>(3, 0));            //for (int i = 0; i < n + 1; i++)            //{            //    for (int j = 0; j < n + 1; j++)            //    {            //        dataFitted.Add(X.At<double>(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<double>(0, 0));            //dataFitted.Add(A.At<double>(1, 0));            //dataFitted.Add(A.At<double>(2, 0));            //dataFitted.Add(A.At<double>(3, 0));            return true;        }        /// <summary>        /// 通过颜色通道去除像素点的千分比计算有效阈值        /// </summary>        /// <param name="hists"></param>        /// <param name="percentValue"></param>        /// <returns></returns>        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.AppWorkspace.ActiveDocumentWorkspace == null)            {                return new OpenCvSharp.Point(1, 254); ;            }            //计算灰度分布密度            float totalPoints = this.AppWorkspace.ActiveDocumentWorkspace.OldMat.Cols * this.AppWorkspace.ActiveDocumentWorkspace.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<float>(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;        }        /// <summary>        /// 更新直方图特征曲线        /// </summary>        /// <param name="updateThreePoints">是否需要更新三个控制点的位置</param>        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<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();            //根据亮度和对比度计算左右阈值            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<List<OpenCvSharp.Point>> pointsIn = new List<List<OpenCvSharp.Point>>()                {                    points                };            //绘制折线	            Cv2.Polylines(image, pointsIn/*(IEnumerable<OpenCvSharp.Point>)(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<OpenCvSharp.Point> points_fitted = new List<OpenCvSharp.Point>(); //std::vector<cv::Point> points_fitted;            List<double> dataFitted = new List<double>();            dataFitted.Add(A.At<double>(0, 0));            dataFitted.Add(A.At<double>(1, 0));            dataFitted.Add(A.At<double>(2, 0));            dataFitted.Add(A.At<double>(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<double>(0, 0) + A.At<double>(1, 0) * x + A.At<double>(2, 0) * Math.Pow(x, 2) + A.At<double>(3, 0) * Math.Pow(x, 3);                points_fitted.Add(new OpenCvSharp.Point(x, y));            }            //List<List<OpenCvSharp.Point>> points_fittedIn = new List<List<OpenCvSharp.Point>>()            //{            //    points_fitted            //};            ////绘制折线	            //Cv2.Polylines(image, points_fittedIn/*(IEnumerable<OpenCvSharp.Point>)(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);        }        /// <summary>        /// 根据亮度、对比度、gamma对图片进行处理        /// </summary>        private void scrollMethod()        {            if (this.AppWorkspace.ActiveDocumentWorkspace == null                 /*|| !this.AppWorkspace.Widgets.HistogramDialog.Visible*/)            {                return;            }            Mat[] mats = Cv2.Split(this.AppWorkspace.ActiveDocumentWorkspace.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);                    //for (int h=0; h< mats[j].Height; h++)                    //{                    //    for (int w = 0; w < mats[j].Width; w++)                    //    {                    //        if(mats[j].At<byte>(h,w)<0) mats[j].Set<byte>(h, w, 0);                    //        if (mats[j].At<byte>(h, w) > 255) mats[j].Set<byte>(h, w, 255);                    //    }                    //}                }                Cv2.Merge(mats, dst);                Cv2.Normalize(dst, dst, 0, 255, NormTypes.MinMax);            }            //灰度归一化            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.FromMat(dst/*this.AppWorkspace.ActiveDocumentWorkspace.OldMat*/);            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<float>(i);            //    }            //    for (int i = grayMax; i < oldHists[j].Rows; i++)            //    {            //        totalPoints[j] = totalPoints[j] - oldHists[j].At<float>(i);            //    }            //}            //for (int j = 0; j < (isGray ? 1 : oldHists.Length); j++)            //{            //    //计算灰度分布密度            //    //List<float> ProbPixel = new List<float>();            //    //计算累计直方图分布            //    List<float> equalizeHists = new List<float>();            //    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<float>(i) / (totalPoints[j] * 1.0)));            //        }            //        else            //        {            //            equalizeHists.Add(equalizeHists[i - 1] + (float)(hist.At<float>(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        }        /// <summary>        /// 拖动左侧三角形        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        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);        }        /// <summary>        /// 拖动中间三角形        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        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);        }        /// <summary>        /// 拖动右侧三角形        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        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);        }        private void HistogramDialog_FormClosing(object sender, FormClosingEventArgs e)        {            this.AppWorkspace.toolBar.RefreshBtnSelect(false, "Histogram");            this.AppWorkspace.toolsPanel.RefreshBtnSelect(false, "Histogram");        }    }}
 |