HistogramDialog.cs 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498
  1. using OpenCvSharp;
  2. using PaintDotNet.CustomControl;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Windows.Forms;
  6. namespace PaintDotNet.Instrument
  7. {
  8. /// <summary>
  9. /// 工具-直方图
  10. /// </summary>
  11. internal class HistogramDialog : FloatingToolForm
  12. {
  13. #region 初始化变量
  14. private AppWorkspace AppWorkspace;
  15. /// <summary>
  16. /// 一个矩阵数组,用来接收直方图,记得全部初始化
  17. /// </summary>
  18. Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };
  19. /// <summary>
  20. /// 灰度图
  21. /// </summary>
  22. private bool isGray = true;
  23. /// <summary>
  24. /// BGR线条颜色
  25. /// </summary>
  26. private Scalar[] color = new Scalar[] { new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255), new Scalar(0, 0, 255, 255) };
  27. #endregion
  28. #region 控件相关
  29. private Button button2;
  30. private Button button3;
  31. private Button button4;
  32. private Button button5;
  33. private Label label1;
  34. private Label label2;
  35. private Label label3;
  36. private NumericUpDown numericUpDown1;
  37. private Label label4;
  38. private CustomControl.TriangleTrackBar trackBar1;
  39. private Label label5;
  40. private Label label6;
  41. private CustomControl.TriangleTrackBar trackBar2;
  42. private Label label7;
  43. private CustomControl.TriangleTrackBar trackBar3;
  44. private CustomControl.SelectButton skipButton;
  45. private CustomControl.SelectButton logButton;
  46. private CustomControl.UCTrackBar ucTrackBar1;
  47. private PictureBox pictureBox1;
  48. private void InitializeLanguageText()
  49. {
  50. this.button2.Text = PdnResources.GetString("Menu.optimal.text");
  51. this.button4.Text = PdnResources.GetString("Menu.Gammavalue.text") + "0.45";
  52. this.button5.Text = PdnResources.GetString("Menu.Originalstate.text");
  53. this.label1.Text = PdnResources.GetString("Menu.luminance.text") + ":";
  54. this.label2.Text = PdnResources.GetString("Menu.Contrast.text") + ":";
  55. this.label3.Text = PdnResources.GetString("Menu.Gammavalue.text") + ":";
  56. }
  57. private void InitializeComponent()
  58. {
  59. this.pictureBox1 = new System.Windows.Forms.PictureBox();
  60. this.button2 = new System.Windows.Forms.Button();
  61. this.button3 = new System.Windows.Forms.Button();
  62. this.button4 = new System.Windows.Forms.Button();
  63. this.button5 = new System.Windows.Forms.Button();
  64. this.label1 = new System.Windows.Forms.Label();
  65. this.label2 = new System.Windows.Forms.Label();
  66. this.label3 = new System.Windows.Forms.Label();
  67. this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
  68. this.label4 = new System.Windows.Forms.Label();
  69. this.trackBar1 = new PaintDotNet.CustomControl.TriangleTrackBar();
  70. this.label5 = new System.Windows.Forms.Label();
  71. this.label6 = new System.Windows.Forms.Label();
  72. this.trackBar2 = new PaintDotNet.CustomControl.TriangleTrackBar();
  73. this.label7 = new System.Windows.Forms.Label();
  74. this.trackBar3 = new PaintDotNet.CustomControl.TriangleTrackBar();
  75. this.skipButton = new PaintDotNet.CustomControl.SelectButton();
  76. this.logButton = new PaintDotNet.CustomControl.SelectButton();
  77. this.ucTrackBar1 = new PaintDotNet.CustomControl.UCTrackBar();
  78. ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
  79. ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
  80. this.SuspendLayout();
  81. //
  82. // pictureBox1
  83. //
  84. this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
  85. | System.Windows.Forms.AnchorStyles.Left)
  86. | System.Windows.Forms.AnchorStyles.Right)));
  87. this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
  88. this.pictureBox1.Location = new System.Drawing.Point(12, 12);
  89. this.pictureBox1.Name = "pictureBox1";
  90. this.pictureBox1.Size = new System.Drawing.Size(256, 124);
  91. this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
  92. this.pictureBox1.TabIndex = 1;
  93. this.pictureBox1.TabStop = false;
  94. //
  95. // button2
  96. //
  97. this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
  98. this.button2.Location = new System.Drawing.Point(126, 274);
  99. this.button2.Name = "button2";
  100. this.button2.Size = new System.Drawing.Size(75, 23);
  101. this.button2.TabIndex = 4;
  102. this.button2.Text = "最佳";
  103. this.button2.UseVisualStyleBackColor = true;
  104. this.button2.Click += new System.EventHandler(this.button2_Click);
  105. //
  106. // button3
  107. //
  108. this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
  109. this.button3.Location = new System.Drawing.Point(241, 303);
  110. this.button3.Name = "button3";
  111. this.button3.Size = new System.Drawing.Size(75, 23);
  112. this.button3.TabIndex = 5;
  113. this.button3.Text = "MIN/MAX";
  114. this.button3.UseVisualStyleBackColor = true;
  115. this.button3.Click += new System.EventHandler(this.button3_Click);
  116. //
  117. // button4
  118. //
  119. this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
  120. this.button4.Location = new System.Drawing.Point(12, 303);
  121. this.button4.Name = "button4";
  122. this.button4.Size = new System.Drawing.Size(75, 23);
  123. this.button4.TabIndex = 6;
  124. this.button4.Text = "伽马值0.45";
  125. this.button4.UseVisualStyleBackColor = true;
  126. this.button4.Click += new System.EventHandler(this.button4_Click);
  127. //
  128. // button5
  129. //
  130. this.button5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
  131. this.button5.Location = new System.Drawing.Point(126, 303);
  132. this.button5.Name = "button5";
  133. this.button5.Size = new System.Drawing.Size(75, 23);
  134. this.button5.TabIndex = 7;
  135. this.button5.Text = "原始状态";
  136. this.button5.UseVisualStyleBackColor = true;
  137. this.button5.Click += new System.EventHandler(this.button5_Click);
  138. //
  139. // label1
  140. //
  141. this.label1.AutoSize = true;
  142. this.label1.Location = new System.Drawing.Point(25, 166);
  143. this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  144. this.label1.Name = "label1";
  145. this.label1.Size = new System.Drawing.Size(41, 12);
  146. this.label1.TabIndex = 9;
  147. this.label1.Text = "亮度:";
  148. //
  149. // label2
  150. //
  151. this.label2.AutoSize = true;
  152. this.label2.Location = new System.Drawing.Point(13, 202);
  153. this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  154. this.label2.Name = "label2";
  155. this.label2.Size = new System.Drawing.Size(53, 12);
  156. this.label2.TabIndex = 10;
  157. this.label2.Text = "对比度:";
  158. //
  159. // label3
  160. //
  161. this.label3.AutoSize = true;
  162. this.label3.Location = new System.Drawing.Point(13, 238);
  163. this.label3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  164. this.label3.Name = "label3";
  165. this.label3.Size = new System.Drawing.Size(53, 12);
  166. this.label3.TabIndex = 11;
  167. this.label3.Text = "伽马值:";
  168. //
  169. // numericUpDown1
  170. //
  171. this.numericUpDown1.Location = new System.Drawing.Point(242, 276);
  172. this.numericUpDown1.Margin = new System.Windows.Forms.Padding(2);
  173. this.numericUpDown1.Maximum = new decimal(new int[] {
  174. 499,
  175. 0,
  176. 0,
  177. 0});
  178. this.numericUpDown1.Name = "numericUpDown1";
  179. this.numericUpDown1.Size = new System.Drawing.Size(50, 21);
  180. this.numericUpDown1.TabIndex = 12;
  181. this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
  182. this.numericUpDown1.Value = new decimal(new int[] {
  183. 200,
  184. 0,
  185. 0,
  186. 0});
  187. this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
  188. //
  189. // label4
  190. //
  191. this.label4.AutoSize = true;
  192. this.label4.Location = new System.Drawing.Point(296, 280);
  193. this.label4.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  194. this.label4.Name = "label4";
  195. this.label4.Size = new System.Drawing.Size(17, 12);
  196. this.label4.TabIndex = 13;
  197. this.label4.Text = "‰";
  198. //
  199. // trackBar1
  200. //
  201. this.trackBar1.Location = new System.Drawing.Point(67, 159);
  202. this.trackBar1.Maximum = 200;
  203. this.trackBar1.Minimum = -200;
  204. this.trackBar1.Name = "trackBar1";
  205. this.trackBar1.Size = new System.Drawing.Size(200, 30);
  206. this.trackBar1.TabIndex = 14;
  207. this.trackBar1.Value = -50;
  208. this.trackBar1.TrackBarScroll += new System.EventHandler(this.trackBar1_Scroll);
  209. //
  210. // label5
  211. //
  212. this.label5.AutoSize = true;
  213. this.label5.Location = new System.Drawing.Point(272, 166);
  214. this.label5.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  215. this.label5.Name = "label5";
  216. this.label5.Size = new System.Drawing.Size(29, 12);
  217. this.label5.TabIndex = 15;
  218. this.label5.Text = "-0.5";
  219. this.label5.TextChanged += new System.EventHandler(this.label5_Changed);
  220. //
  221. // label6
  222. //
  223. this.label6.AutoSize = true;
  224. this.label6.Location = new System.Drawing.Point(272, 202);
  225. this.label6.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  226. this.label6.Name = "label6";
  227. this.label6.Size = new System.Drawing.Size(29, 12);
  228. this.label6.TabIndex = 17;
  229. this.label6.Text = "1.00";
  230. this.label6.TextChanged += new System.EventHandler(this.label6_Changed);
  231. //
  232. // trackBar2
  233. //
  234. this.trackBar2.Location = new System.Drawing.Point(67, 195);
  235. this.trackBar2.Maximum = 999;
  236. this.trackBar2.Minimum = 0;
  237. this.trackBar2.Name = "trackBar2";
  238. this.trackBar2.Size = new System.Drawing.Size(200, 30);
  239. this.trackBar2.TabIndex = 16;
  240. this.trackBar2.Value = 100;
  241. this.trackBar2.TrackBarScroll += new System.EventHandler(this.trackBar2_Scroll);
  242. //
  243. // label7
  244. //
  245. this.label7.AutoSize = true;
  246. this.label7.Location = new System.Drawing.Point(272, 238);
  247. this.label7.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  248. this.label7.Name = "label7";
  249. this.label7.Size = new System.Drawing.Size(29, 12);
  250. this.label7.TabIndex = 19;
  251. this.label7.Text = "1.00";
  252. this.label7.TextChanged += new System.EventHandler(this.label7_Changed);
  253. //
  254. // trackBar3
  255. //
  256. this.trackBar3.Location = new System.Drawing.Point(67, 230);
  257. this.trackBar3.Maximum = 299;
  258. this.trackBar3.Minimum = 0;
  259. this.trackBar3.Name = "trackBar3";
  260. this.trackBar3.Size = new System.Drawing.Size(200, 30);
  261. this.trackBar3.TabIndex = 18;
  262. this.trackBar3.Value = 100;
  263. this.trackBar3.TrackBarScroll += new System.EventHandler(this.trackBar3_Scroll);
  264. //
  265. // skipButton
  266. //
  267. this.skipButton.BackColor = System.Drawing.SystemColors.ControlDark;
  268. this.skipButton.BtnSelect = false;
  269. this.skipButton.BtnText = "skip";
  270. this.skipButton.Location = new System.Drawing.Point(275, 77);
  271. this.skipButton.Name = "skipButton";
  272. this.skipButton.Size = new System.Drawing.Size(41, 21);
  273. this.skipButton.TabIndex = 20;
  274. this.skipButton.Click += new System.EventHandler(this.skipButton_Click);
  275. //
  276. // logButton
  277. //
  278. this.logButton.BackColor = System.Drawing.SystemColors.ControlDark;
  279. this.logButton.BtnSelect = false;
  280. this.logButton.BtnText = "log";
  281. this.logButton.Location = new System.Drawing.Point(275, 46);
  282. this.logButton.Name = "logButton";
  283. this.logButton.Size = new System.Drawing.Size(41, 21);
  284. this.logButton.TabIndex = 21;
  285. this.logButton.Click += new System.EventHandler(this.logButton_Click);
  286. //
  287. // ucTrackBar1
  288. //
  289. this.ucTrackBar1.DcimalDigits = 0;
  290. this.ucTrackBar1.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(77)))), ((int)(((byte)(59)))));
  291. this.ucTrackBar1.LineWidth = 8F;
  292. this.ucTrackBar1.Location = new System.Drawing.Point(4, 139);
  293. this.ucTrackBar1.MaxValue = 255F;
  294. this.ucTrackBar1.MinValue = 0F;
  295. this.ucTrackBar1.Name = "ucTrackBar1";
  296. this.ucTrackBar1.Size = new System.Drawing.Size(274, 20);
  297. this.ucTrackBar1.TabIndex = 22;
  298. this.ucTrackBar1.Text = "ucTrackBar1";
  299. this.ucTrackBar1.Value1 = 0F;
  300. this.ucTrackBar1.Value2 = 127F;
  301. this.ucTrackBar1.Value3 = 255F;
  302. this.ucTrackBar1.Value1Changed += new System.EventHandler(this.ucTrackBar1_Value1Changed);
  303. this.ucTrackBar1.Value2Changed += new System.EventHandler(this.ucTrackBar1_Value2Changed);
  304. this.ucTrackBar1.Value3Changed += new System.EventHandler(this.ucTrackBar1_Value3Changed);
  305. //
  306. // HistogramDialog
  307. //
  308. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
  309. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  310. this.ClientSize = new System.Drawing.Size(325, 338);
  311. this.Controls.Add(this.ucTrackBar1);
  312. this.Controls.Add(this.logButton);
  313. this.Controls.Add(this.skipButton);
  314. this.Controls.Add(this.label7);
  315. this.Controls.Add(this.trackBar3);
  316. this.Controls.Add(this.label6);
  317. this.Controls.Add(this.trackBar2);
  318. this.Controls.Add(this.label5);
  319. this.Controls.Add(this.trackBar1);
  320. this.Controls.Add(this.label4);
  321. this.Controls.Add(this.numericUpDown1);
  322. this.Controls.Add(this.label3);
  323. this.Controls.Add(this.label2);
  324. this.Controls.Add(this.label1);
  325. this.Controls.Add(this.button5);
  326. this.Controls.Add(this.button4);
  327. this.Controls.Add(this.button3);
  328. this.Controls.Add(this.button2);
  329. this.Controls.Add(this.pictureBox1);
  330. this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
  331. this.Margin = new System.Windows.Forms.Padding(6);
  332. this.Name = "HistogramDialog";
  333. this.Text = "直方图";
  334. this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.HistogramDialog_FormClosing);
  335. this.Controls.SetChildIndex(this.pictureBox1, 0);
  336. this.Controls.SetChildIndex(this.button2, 0);
  337. this.Controls.SetChildIndex(this.button3, 0);
  338. this.Controls.SetChildIndex(this.button4, 0);
  339. this.Controls.SetChildIndex(this.button5, 0);
  340. this.Controls.SetChildIndex(this.label1, 0);
  341. this.Controls.SetChildIndex(this.label2, 0);
  342. this.Controls.SetChildIndex(this.label3, 0);
  343. this.Controls.SetChildIndex(this.numericUpDown1, 0);
  344. this.Controls.SetChildIndex(this.label4, 0);
  345. this.Controls.SetChildIndex(this.trackBar1, 0);
  346. this.Controls.SetChildIndex(this.label5, 0);
  347. this.Controls.SetChildIndex(this.trackBar2, 0);
  348. this.Controls.SetChildIndex(this.label6, 0);
  349. this.Controls.SetChildIndex(this.trackBar3, 0);
  350. this.Controls.SetChildIndex(this.label7, 0);
  351. this.Controls.SetChildIndex(this.skipButton, 0);
  352. this.Controls.SetChildIndex(this.logButton, 0);
  353. this.Controls.SetChildIndex(this.ucTrackBar1, 0);
  354. ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
  355. ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
  356. this.ResumeLayout(false);
  357. this.PerformLayout();
  358. }
  359. #endregion
  360. public HistogramDialog(AppWorkspace AppWorkspace)
  361. {
  362. this.AppWorkspace = AppWorkspace;
  363. InitializeComponent();
  364. InitializeLanguageText();
  365. this.Text = PdnResources.GetString("Menu.Tools.Histogram.Text");/*;//待修改中文资源-scc备注 20200108*/
  366. if (this.AppWorkspace.ActiveDocumentWorkspace != null)
  367. {
  368. Mat[] mats = Cv2.Split(this.AppWorkspace.ActiveDocumentWorkspace.BoxMat);//一张图片,将panda拆分成3个图片装进mat
  369. Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  370. Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  371. Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  372. int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  373. int[] channels1 = new int[] { 0 };
  374. int[] channels2 = new int[] { 0 };
  375. int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  376. Rangef[] range = new Rangef[1];//一个通道,范围
  377. range[0].Start = 0.0F;//从0开始(含)
  378. range[0].End = 256.0F;//到256结束(不含)
  379. Mat mask = new Mat();//不做掩码
  380. Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  381. Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  382. Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  383. for (int h = 0; h < oldHists[0].Rows; h++)
  384. {
  385. for (int j = oldHists.Length - 1; j >= 1; j--)
  386. {
  387. if (oldHists[j].At<float>(h) != oldHists[0].At<float>(h))
  388. {
  389. isGray = false;
  390. break;
  391. }
  392. }
  393. if (!isGray)
  394. break;
  395. }
  396. updateHistImg(oldHists);
  397. updateHistogramRect(false);
  398. ////根据亮度和对比度计算左右阈值
  399. //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);
  400. //int grayMax = (int)((256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) - double.Parse(label5.Text) * 510.0) / 2.0);
  401. //if (grayMin >= grayMax)
  402. //{
  403. // return;
  404. //}
  405. //ucTrackBar1.Value1 = grayMin;
  406. //ucTrackBar1.Value3 = grayMax;
  407. //ucTrackBar1.Value2 = (float)((grayMin + grayMax) / 2.0);
  408. }
  409. if(this.AppWorkspace != null)
  410. this.AppWorkspace.ActiveDocumentWorkspaceChanged += new EventHandler(ButtonFocus);//切换窗口
  411. //if (this.AppWorkspace.ActiveDocumentWorkspace != null)
  412. //{
  413. // this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramBeta = -0.5;
  414. // this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramAlpha = 1.00;
  415. // this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramGamma = 1.00;
  416. // this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramPercent = 200;
  417. // this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramSkipEnabled = false;
  418. // this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramLogEnabled = false;
  419. //}
  420. }
  421. /// <summary>
  422. /// 更改按钮焦点
  423. /// </summary>
  424. /// <param name="dis">按钮区分</param>
  425. public void ButtonFocus(object sender, EventArgs e)
  426. {
  427. if(AppWorkspace != null && AppWorkspace.ActiveDocumentWorkspace != null)
  428. {
  429. // 最佳
  430. if (AppWorkspace.ActiveDocumentWorkspace.buttonType == 0)
  431. {
  432. this.button2.Focus();
  433. }
  434. // 最大最小
  435. if (AppWorkspace.ActiveDocumentWorkspace.buttonType == 1)
  436. {
  437. this.button3.Focus();
  438. }
  439. // 伽马45
  440. if (AppWorkspace.ActiveDocumentWorkspace.buttonType == 2)
  441. {
  442. this.button4.Focus();
  443. }
  444. // 原始
  445. if (AppWorkspace.ActiveDocumentWorkspace.buttonType == 3)
  446. {
  447. this.button5.Focus();
  448. }
  449. }
  450. }
  451. /// <summary>
  452. /// 最佳
  453. /// </summary>
  454. public void BestButtonMethod()
  455. {
  456. OpenCvSharp.Point startIndex = this.getStartIndex(this.AppWorkspace.ActiveDocumentWorkspace.OldMat, oldHists, (float)numericUpDown1.Value);
  457. //计算对比度
  458. label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
  459. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  460. //计算亮度
  461. label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
  462. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  463. this.scrollMethod();
  464. updateHistogramRect(true);
  465. }
  466. /// <summary>
  467. /// 最大最小
  468. /// </summary>
  469. public void MaxMinButtonMethod()
  470. {
  471. OpenCvSharp.Point startIndex = this.getStartIndex(this.AppWorkspace.ActiveDocumentWorkspace.OldMat, oldHists, 0);
  472. //计算对比度
  473. label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
  474. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  475. //计算亮度
  476. label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
  477. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  478. this.scrollMethod();
  479. updateHistogramRect(true);
  480. }
  481. /// <summary>
  482. /// 原始状态
  483. /// </summary>
  484. public void OriginButtonMethod()
  485. {
  486. this.trackBar1.Value = -50;
  487. this.trackBar2.Value = 100;
  488. this.trackBar3.Value = 100;
  489. label5.Text = (trackBar1.Value / 100.0).ToString("f2");
  490. label6.Text = (trackBar2.Value / 100.0).ToString("f2");
  491. label7.Text = (trackBar3.Value / 100.0).ToString("f2");
  492. if (this.AppWorkspace.ActiveDocumentWorkspace == null)
  493. {
  494. MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));
  495. return;
  496. }
  497. this.scrollMethod();
  498. updateHistogramRect(true);
  499. /**待处理**///this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.ResetBoxBitmap();
  500. //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(oldMat));
  501. }
  502. /// <summary>
  503. /// 伽马0.45
  504. /// </summary>
  505. public void Gamma45ButtonMethod()
  506. {
  507. this.trackBar3.Value = 45;
  508. label7.Text = (trackBar3.Value / 100.0).ToString("f2");
  509. this.scrollMethod();
  510. updateHistogramRect(true);
  511. }
  512. /// <summary>
  513. /// 重置Mat
  514. /// </summary>
  515. public void ResetMat()
  516. {
  517. if (this.AppWorkspace.ActiveDocumentWorkspace == null
  518. || this.AppWorkspace.ActiveDocumentWorkspace.OldMat==null)
  519. {
  520. this.Visible = false;
  521. isGray = true;//#18235
  522. //updateHistImg(oldHists);
  523. //updateHistogramRect(true);
  524. return;
  525. }
  526. isGray = true;
  527. Mat[] mats = Cv2.Split(this.AppWorkspace.ActiveDocumentWorkspace.OldMat);//一张图片,将panda拆分成3个图片装进mat
  528. Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  529. Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  530. Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  531. int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  532. int[] channels1 = new int[] { 0 };
  533. int[] channels2 = new int[] { 0 };
  534. int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  535. Rangef[] range = new Rangef[1];//一个通道,范围
  536. range[0].Start = 0.0F;//从0开始(含)
  537. range[0].End = 256.0F;//到256结束(不含)
  538. Mat mask = new Mat();//不做掩码
  539. Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  540. Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  541. Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  542. for (int h = 0; h < oldHists[0].Rows; h++)
  543. {
  544. for (int j = oldHists.Length - 1; j >= 1; j--)
  545. {
  546. if (oldHists[j].At<float>(h) != oldHists[0].At<float>(h))
  547. {
  548. isGray = false;
  549. break;
  550. }
  551. }
  552. if (!isGray)
  553. break;
  554. }
  555. if (this.AppWorkspace.ActiveDocumentWorkspace != null)
  556. {
  557. //获取gamma值
  558. double gamma = this.AppWorkspace.ActiveDocumentWorkspace.HistogramGamma;
  559. this.trackBar3.Value = Math.Min(299, (int)(gamma * 100));//备注:需要与AxioVision进行比较效果,调试一致
  560. label7.Text = gamma.ToString("f2");
  561. //获取对比度
  562. double alpha = this.AppWorkspace.ActiveDocumentWorkspace.HistogramAlpha;
  563. //获取亮度
  564. double beta = this.AppWorkspace.ActiveDocumentWorkspace.HistogramBeta;
  565. //计算对比度
  566. label6.Text = alpha.ToString("f2");
  567. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  568. //计算亮度
  569. if (beta != double.Parse(label5.Text))
  570. {
  571. label5.Text = beta.ToString("f2");
  572. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  573. }
  574. this.numericUpDown1.Value = new decimal(new int[] {
  575. (int)this.AppWorkspace.ActiveDocumentWorkspace.HistogramPercent,
  576. 0,
  577. 0,
  578. 0});
  579. //numericUpDown1.Value = (decimal)this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramPercent;
  580. skipButton.BtnSelect = this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled;
  581. logButton.BtnSelect = this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled;
  582. }
  583. updateHistImg(null);
  584. updateHistogramRect(true);
  585. }
  586. /// <summary>
  587. /// 最佳
  588. /// 确定当前直方图中排除图像中包含的像素的1‰的值,
  589. /// 并在屏幕上显示以此方式确定的灰度或颜色范围。
  590. /// (您可以将1‰的值调整为适合您的需求。)
  591. /// https://blog.csdn.net/qq_20095389/article/details/83658878
  592. /// https://blog.csdn.net/lantishua/article/details/46377325
  593. /// </summary>
  594. /// <param name="sender"></param>
  595. /// <param name="e"></param>
  596. private void button2_Click(object sender, EventArgs e)
  597. {
  598. if (this.AppWorkspace.ActiveDocumentWorkspace == null)
  599. {
  600. MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));
  601. return;
  602. }
  603. this.BestButtonMethod();
  604. this.AppWorkspace.MaxMinBest(true, false, false, false);
  605. }
  606. /// <summary>
  607. /// 最大最小
  608. /// </summary>
  609. /// <param name="sender"></param>
  610. /// <param name="e"></param>
  611. private void button3_Click(object sender, EventArgs e)
  612. {
  613. if (this.AppWorkspace.ActiveDocumentWorkspace == null)
  614. {
  615. MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));
  616. return;
  617. }
  618. this.MaxMinButtonMethod();
  619. this.AppWorkspace.MaxMinBest(false, true, false, false);
  620. }
  621. /// <summary>
  622. /// 伽马0.45
  623. /// 需要调整直线的弧度
  624. /// 直方图曲线根据伽马值进行变化
  625. /// </summary>
  626. /// <param name="sender"></param>
  627. /// <param name="e"></param>
  628. private void button4_Click(object sender, EventArgs e)
  629. {
  630. if (this.AppWorkspace.ActiveDocumentWorkspace == null)
  631. {
  632. MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));
  633. return;
  634. }
  635. this.Gamma45ButtonMethod();
  636. this.AppWorkspace.MaxMinBest(false, false, false, true);
  637. }
  638. /// <summary>
  639. /// 原始状态
  640. /// </summary>
  641. /// <param name="sender"></param>
  642. /// <param name="e"></param>
  643. private void button5_Click(object sender, EventArgs e)
  644. {
  645. this.OriginButtonMethod();
  646. this.AppWorkspace.MaxMinBest(false, false, true, false);
  647. }
  648. /// <summary>
  649. /// skip按钮
  650. /// 显示直方图时,忽略黑色的灰度或颜色值。
  651. /// 这使您可以为背景为黑色的图像实现有意义的直方图显示。
  652. /// </summary>
  653. /// <param name="sender"></param>
  654. /// <param name="e"></param>
  655. private void skipButton_Click(object sender, EventArgs e)
  656. {
  657. if (this.AppWorkspace.ActiveDocumentWorkspace == null)
  658. {
  659. MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));
  660. return;
  661. }
  662. //设置按钮的选中/非选择的状态
  663. skipButton.BtnSelect = !skipButton.BtnSelect;
  664. this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled = skipButton.BtnSelect;
  665. updateHistImg(null);
  666. }
  667. /// <summary>
  668. /// log按钮
  669. /// 以对数比例显示直方图
  670. /// </summary>
  671. /// <param name="sender"></param>
  672. /// <param name="e"></param>
  673. private void logButton_Click(object sender, EventArgs e)
  674. {
  675. if (this.AppWorkspace.ActiveDocumentWorkspace == null)
  676. {
  677. MessageBox.Show(PdnResources.GetString("Menu.Pleaseopenthepicture.Text"));
  678. return;
  679. }
  680. //设置按钮的选中/非选择的状态
  681. logButton.BtnSelect = !logButton.BtnSelect;
  682. this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled = logButton.BtnSelect;
  683. updateHistImg(null);
  684. }
  685. /// <summary>
  686. /// 最佳设置的数值改变
  687. /// </summary>
  688. /// <param name="sender"></param>
  689. /// <param name="e"></param>
  690. private void numericUpDown1_ValueChanged(object sender, EventArgs e)
  691. {
  692. if(this.AppWorkspace.ActiveDocumentWorkspace!=null)
  693. this.AppWorkspace.ActiveDocumentWorkspace.HistogramPercent = (int)numericUpDown1.Value;
  694. }
  695. /// <summary>
  696. /// 亮度改变
  697. /// </summary>
  698. /// <param name="sender"></param>
  699. /// <param name="e"></param>
  700. private void trackBar1_Scroll(object sender, EventArgs e)
  701. {
  702. //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramBeta = trackBar1.Value / 100.0;
  703. label5.Text = (trackBar1.Value / 100.0).ToString("f2");
  704. this.scrollMethod();
  705. updateHistogramRect(true);
  706. }
  707. /// <summary>
  708. /// 亮度改变
  709. /// </summary>
  710. /// <param name="sender"></param>
  711. /// <param name="e"></param>
  712. private void label5_Changed(object sender, EventArgs e)
  713. {
  714. if(this.AppWorkspace.ActiveDocumentWorkspace!=null)
  715. {
  716. this.AppWorkspace.ActiveDocumentWorkspace.HistogramBeta = double.Parse(label5.Text);
  717. //this.scrollMethod();
  718. }
  719. }
  720. /// <summary>
  721. /// 对比度改变
  722. /// </summary>
  723. /// <param name="sender"></param>
  724. /// <param name="e"></param>
  725. private void trackBar2_Scroll(object sender, EventArgs e)
  726. {
  727. label6.Text = (trackBar2.Value / 100.0).ToString("f2");
  728. this.scrollMethod();
  729. updateHistogramRect(true);
  730. }
  731. /// <summary>
  732. /// 对比度改变
  733. /// </summary>
  734. /// <param name="sender"></param>
  735. /// <param name="e"></param>
  736. private void label6_Changed(object sender, EventArgs e)
  737. {
  738. if (this.AppWorkspace.ActiveDocumentWorkspace != null)
  739. {
  740. this.AppWorkspace.ActiveDocumentWorkspace.HistogramAlpha = double.Parse(label6.Text);
  741. //this.scrollMethod();
  742. }
  743. }
  744. /// <summary>
  745. /// gamma改变
  746. /// gamma值小于1时,会拉伸图像中灰度级较低的区域,同时会压缩灰度级较高的部分
  747. /// gamma值大于1时,会拉伸图像中灰度级较高的区域,同时会压缩灰度级较低的部分
  748. /// </summary>
  749. /// <param name="sender"></param>
  750. /// <param name="e"></param>
  751. private void trackBar3_Scroll(object sender, EventArgs e)
  752. {
  753. label7.Text = (trackBar3.Value / 100.0).ToString("f2");
  754. this.scrollMethod();
  755. updateHistogramRect(true);
  756. }
  757. /// <summary>
  758. /// gamma改变
  759. /// </summary>
  760. /// <param name="sender"></param>
  761. /// <param name="e"></param>
  762. private void label7_Changed(object sender, EventArgs e)
  763. {
  764. this.AppWorkspace.ActiveDocumentWorkspace.HistogramGamma = double.Parse(label7.Text);
  765. //this.scrollMethod();
  766. }
  767. /// <summary>
  768. /// 绘制直方图
  769. /// </summary>
  770. /// <param name="hist"></param>
  771. /// <returns></returns>
  772. private unsafe void updateHistImg(Mat[] hists)
  773. {
  774. if (this.AppWorkspace.ActiveDocumentWorkspace == null
  775. || this.AppWorkspace.ActiveDocumentWorkspace.OldMat==null)
  776. {
  777. return;
  778. }
  779. Mat[] mats = Cv2.Split(this.AppWorkspace.ActiveDocumentWorkspace.OldMat);//一张图片,将panda拆分成3个图片装进mat
  780. Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  781. Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  782. Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  783. if (hists == null)
  784. {
  785. hists = new Mat[] { new Mat(), new Mat(), new Mat() };//一个矩阵数组,用来接收直方图,记得全部初始化
  786. int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  787. int[] channels1 = new int[] { 0 };
  788. int[] channels2 = new int[] { 0 };
  789. int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  790. Rangef[] range = new Rangef[1];//一个通道,范围
  791. range[0].Start = 0.0F;//从0开始(含)
  792. range[0].End = 256.0F;//到256结束(不含)
  793. Mat mask = new Mat();//不做掩码
  794. Cv2.CalcHist(mats0, channels0, mask, hists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  795. Cv2.CalcHist(mats1, channels1, mask, hists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  796. Cv2.CalcHist(mats2, channels2, mask, hists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  797. if (logButton.BtnSelect)
  798. {
  799. //取对数
  800. for (int j = 0; j < hists.Length; j++)
  801. {
  802. List<float> ProbPixel = new List<float>();
  803. for (int i = 0; i < hists[j].Rows; i++)
  804. {
  805. if (((float*)hists[j].Ptr(0))[i] == 0)
  806. {
  807. ((float*)hists[j].Ptr(0))[i] = ((float*)hists[j].Ptr(0))[i];
  808. ProbPixel.Add(0);
  809. }
  810. else
  811. {
  812. ((float*)hists[j].Ptr(0))[i] = (float)Math.Log10(((float*)hists[j].Ptr(0))[i]/* + 9*/);
  813. ProbPixel.Add(1);
  814. }
  815. }
  816. double max1jVal = 0;
  817. double min1jVal = 0;
  818. //找到直方图中的最大值和最小值
  819. Cv2.MinMaxLoc(hists[j], out min1jVal, out max1jVal);
  820. if (min1jVal >= max1jVal)
  821. {
  822. continue;
  823. }
  824. //归一化到0~255,并根据AxioVision添加偏置值
  825. for (int i = 0; i < hists[j].Rows; i++)
  826. {
  827. ((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);
  828. }
  829. }
  830. }
  831. if (skipButton.BtnSelect)
  832. {
  833. //去掉黑色部分 和 白色部分
  834. for (int j = 0; j < hists.Length; j++)
  835. {
  836. ((float*)hists[j].Ptr(0))[0] = 0;
  837. ((float*)hists[j].Ptr(0))[255] = 0;
  838. }
  839. }
  840. }
  841. double max2Val = 0;
  842. double max1Val = 0;
  843. double max0Val = 0;
  844. double minVal = 0;
  845. //为了更好显示直方图细节,使用4倍尺寸绘制直方图
  846. int histSize = hists[0].Rows * 4;
  847. Mat histImg = new Mat(histSize, histSize, MatType.CV_8UC3, new Scalar(255, 255, 255));
  848. //找到直方图中的最大值和最小值
  849. Cv2.MinMaxLoc(hists[2], out minVal, out max2Val);
  850. Cv2.MinMaxLoc(hists[1], out minVal, out max1Val);
  851. Cv2.MinMaxLoc(hists[0], out minVal, out max0Val);
  852. double maxVal = Math.Max(max2Val, Math.Max(max0Val, max1Val));
  853. if (maxVal < 1)
  854. return;
  855. // 设置最大峰值为图像高度的90%
  856. double hpt = 0.9 * histSize;
  857. //灰度图的显示直方图较为简单,显示一个通道即可
  858. if (isGray)
  859. {
  860. Mat hist = hists[0];
  861. int lastY2 = histSize - 1;
  862. for (int h = 0; h < hists[0].Rows; h++)
  863. {
  864. int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  865. int lastY1 = lastY2;
  866. lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  867. if (lastY2 < lastY1)
  868. {
  869. 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);
  870. }
  871. else
  872. {
  873. 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);
  874. }
  875. }
  876. }
  877. //彩度图显示BGR三个通道的直方图
  878. else
  879. {
  880. int lineWidth = 2;
  881. for (int j = hists.Length - 1; j >= 0; j--)
  882. {
  883. Mat hist = hists[j];
  884. int lastY2 = histSize - 1;
  885. for (int h = 0; h < hists[0].Rows; h++)
  886. {
  887. int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  888. int lastY1 = lastY2;
  889. lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  890. if (h > 0)
  891. {
  892. //显示0.5位置的直方图,这样与AxioVision效果更加近似
  893. int lasty12 = (lastY1 + lastY2) / 2;
  894. if (lasty12 < lastY1)
  895. {
  896. 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);
  897. }
  898. else
  899. {
  900. 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*/);
  901. }
  902. if (lastY2 < lasty12)
  903. {
  904. Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lasty12 - 2)), color[j], lineWidth, LineTypes.Link4);
  905. }
  906. else
  907. {
  908. 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*/);
  909. }
  910. }
  911. else
  912. {
  913. //灰度值为0的线的绘制
  914. if (lastY2 < lastY1)
  915. {
  916. Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
  917. }
  918. else
  919. {
  920. 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*/);
  921. }
  922. }
  923. }
  924. }
  925. }
  926. this.pictureBox1.BackgroundImage/*Image*/ = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  927. }
  928. /// <summary>
  929. /// 测试曲线拟合的代码
  930. /// </summary>
  931. private void testCurveFit()
  932. {
  933. //创建用于绘制的深蓝色背景图像
  934. 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));
  935. //输入拟合点
  936. List<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();// std::vector<cv::Point> points;
  937. points.Add(new OpenCvSharp.Point(0, 254));
  938. points.Add(new OpenCvSharp.Point(127, 222/*32*/));
  939. points.Add(new OpenCvSharp.Point(254, 0));
  940. //points.Add(new OpenCvSharp.Point(100, 58));
  941. //points.Add(new OpenCvSharp.Point(150, 70));
  942. //points.Add(new OpenCvSharp.Point(200, 90));
  943. ////points.push_back(cv::Point(100., 58.)); points.push_back(cv::Point(150., 70.)); points.push_back(cv::Point(200., 90.));
  944. //points.Add(new OpenCvSharp.Point(252, 140));
  945. //points.Add(new OpenCvSharp.Point(300, 220));
  946. //points.Add(new OpenCvSharp.Point(350, 400));
  947. //points.push_back(cv::Point(252., 140.)); points.push_back(cv::Point(300., 220.)); points.push_back(cv::Point(350., 400.));
  948. List<List<OpenCvSharp.Point>> pointsIn = new List<List<OpenCvSharp.Point>>()
  949. {
  950. points
  951. };
  952. //将拟合点绘制到空白图上
  953. for (int i = 0; i < points.Count; i++)
  954. {
  955. Cv2.Circle(image, points[i].X, points[i].Y, 5, new Scalar(0, 0, 255), 2, LineTypes.Link8, 0);
  956. //cv::circle(image, points[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
  957. }
  958. //绘制折线
  959. 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);
  960. Mat A = new Mat(3 + 1/*480*/, 1/*640*/, MatType.CV_64FC1, new Scalar(0));// cv::Mat A;
  961. polynomial_curve_fit(points.ToArray(), 3, A);
  962. //std::cout << "A = " << A << std::endl;
  963. List<OpenCvSharp.Point> points_fitted = new List<OpenCvSharp.Point>(); //std::vector<cv::Point> points_fitted;
  964. List<double> dataFitted = new List<double>();
  965. dataFitted.Add(A.At<double>(0, 0));
  966. dataFitted.Add(A.At<double>(1, 0));
  967. dataFitted.Add(A.At<double>(2, 0));
  968. dataFitted.Add(A.At<double>(3, 0));
  969. for (int x = 0; x < 255; x++)
  970. {
  971. 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);
  972. // 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);
  973. points_fitted.Add(new OpenCvSharp.Point(x, y));
  974. // points_fitted.push_back(cv::Point(x, y));
  975. }
  976. List<List<OpenCvSharp.Point>> points_fittedIn = new List<List<OpenCvSharp.Point>>()
  977. {
  978. points_fitted
  979. };
  980. //黄色线表示拟合后的曲线,成功
  981. 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);
  982. Cv2.ImShow("image", image);// cv::imshow("image", image);
  983. //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  984. }
  985. /// <summary>
  986. /// 将拟合点绘制到空白图上
  987. /// //原文链接:https://blog.csdn.net/guduruyu/article/details/72866144
  988. /// </summary>
  989. /// <param name="key_point">拟合点</param>
  990. /// <param name="n">拟合矩阵的??数量</param>
  991. /// <param name="A">空白图</param>
  992. /// <returns></returns>
  993. private unsafe bool polynomial_curve_fit(OpenCvSharp.Point[] key_point, int n, Mat A)
  994. {
  995. //Number of key points
  996. int N = key_point.Length;
  997. //构造矩阵X
  998. 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);
  999. for (int i = 0; i < n + 1; i++)
  1000. {
  1001. for (int j = 0; j < n + 1; j++)
  1002. {
  1003. ((double*)X.Ptr(i))[j] = 0;//111
  1004. for (int k = 0; k < N; k++)
  1005. {
  1006. ((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);
  1007. }
  1008. }
  1009. }
  1010. //构造矩阵Y
  1011. Mat Y = new Mat(n + 1, 1, MatType.CV_64FC1, new Scalar(0));// cv::Mat Y = cv::Mat::zeros(n + 1, 1, CV_64FC1);
  1012. for (int i = 0; i < n + 1; i++)
  1013. {
  1014. ((double*)Y.Ptr(i))[0] = 0;//111
  1015. for (int k = 0; k < N; k++)
  1016. {
  1017. ((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;
  1018. }
  1019. }
  1020. //A = new Mat(n + 1, 1, MatType.CV_64FC1, new Scalar(0));// A = cv::Mat::zeros(n + 1, 1, CV_64FC1);
  1021. //List<double> dataFitted = new List<double>();
  1022. //dataFitted.Add(Y.At<double>(0, 0));
  1023. //dataFitted.Add(Y.At<double>(1, 0));
  1024. //dataFitted.Add(Y.At<double>(2, 0));
  1025. //dataFitted.Add(Y.At<double>(3, 0));
  1026. //for (int i = 0; i < n + 1; i++)
  1027. //{
  1028. // for (int j = 0; j < n + 1; j++)
  1029. // {
  1030. // dataFitted.Add(X.At<double>(i, j));
  1031. // }
  1032. //}
  1033. //求解矩阵A
  1034. Cv2.Solve(X, Y, A, DecompTypes.LU);//Cv2.Solve(X, Y, A, DecompTypes.LU); cv::solve(X, Y, A, cv::DECOMP_LU);
  1035. //dataFitted.Add(A.At<double>(0, 0));
  1036. //dataFitted.Add(A.At<double>(1, 0));
  1037. //dataFitted.Add(A.At<double>(2, 0));
  1038. //dataFitted.Add(A.At<double>(3, 0));
  1039. return true;
  1040. }
  1041. /// <summary>
  1042. /// 通过颜色通道去除像素点的千分比计算有效阈值
  1043. /// </summary>
  1044. /// <param name="hists"></param>
  1045. /// <param name="percentValue"></param>
  1046. /// <returns></returns>
  1047. private OpenCvSharp.Point getStartIndex(Mat mat, Mat[] hists, float percentValue)
  1048. {
  1049. //灰度化图片取第一通道
  1050. Mat histGray = hists[0];
  1051. //彩色图片取灰度化后的通道
  1052. if (!isGray)
  1053. {
  1054. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(0, histGray.Rows);
  1055. //计算三次
  1056. OpenCvSharp.Point startIndex0 = this.getStartRange(mat, hists[0], percentValue);
  1057. OpenCvSharp.Point startIndex1 = this.getStartRange(mat, hists[1], percentValue);
  1058. OpenCvSharp.Point startIndex2 = this.getStartRange(mat, hists[2], percentValue);
  1059. startIndex.X = Math.Min(startIndex0.X, Math.Min(startIndex1.X, startIndex2.X));
  1060. startIndex.Y = Math.Max(startIndex0.Y, Math.Max(startIndex1.Y, startIndex2.Y));
  1061. startIndex.Y = Math.Min(255 - 1, startIndex.Y);
  1062. startIndex.X = Math.Max(startIndex.X, 1);
  1063. startIndex.Y = Math.Max(startIndex.X + 1, startIndex.Y);
  1064. return startIndex;
  1065. }
  1066. return this.getStartRange(mat, histGray, percentValue);
  1067. }
  1068. private OpenCvSharp.Point getStartRange(Mat mat, Mat histGray, float percentValue)
  1069. {
  1070. if (this.AppWorkspace.ActiveDocumentWorkspace == null)
  1071. {
  1072. return new OpenCvSharp.Point(1, 254); ;
  1073. }
  1074. //计算灰度分布密度
  1075. float totalPoints = this.AppWorkspace.ActiveDocumentWorkspace.OldMat.Cols * this.AppWorkspace.ActiveDocumentWorkspace.OldMat.Rows;
  1076. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(0, histGray.Rows);
  1077. bool foundStartTag = false;
  1078. bool foundEndTag = false;
  1079. //根据累计直方图分布计算左右阈值
  1080. float equalizeHists = 0;
  1081. for (int i = 0; i < histGray.Rows; ++i)
  1082. {
  1083. equalizeHists += ((float)(histGray.At<float>(i) / (totalPoints * 1.0))) * 1000;
  1084. if (!foundStartTag && equalizeHists > percentValue)
  1085. {
  1086. foundStartTag = true;
  1087. startIndex.X = i;
  1088. }
  1089. else if (equalizeHists >= 1000 - percentValue)
  1090. {
  1091. foundEndTag = true;
  1092. startIndex.Y = i;
  1093. }
  1094. if (foundStartTag && foundEndTag)
  1095. break;
  1096. }
  1097. startIndex.Y = Math.Min(255 - 1, startIndex.Y);
  1098. startIndex.X = Math.Max(startIndex.X, 1);
  1099. startIndex.Y = Math.Max(startIndex.X + 1, startIndex.Y);
  1100. return startIndex;
  1101. }
  1102. /// <summary>
  1103. /// 更新直方图特征曲线
  1104. /// </summary>
  1105. /// <param name="updateThreePoints">是否需要更新三个控制点的位置</param>
  1106. private void updateHistogramRect(bool updateThreePoints)
  1107. {
  1108. //为了更好显示直方图细节,使用4倍尺寸绘制直方图
  1109. int histSize = 256/*oldHists[0].Rows*/ * 4;
  1110. //创建用于绘制的深蓝色背景图像
  1111. Mat image = new Mat(histSize, histSize, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  1112. //输入拟合点
  1113. List<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();
  1114. //根据亮度和对比度计算左右阈值
  1115. 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);
  1116. int grayMax = (int)((256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) - double.Parse(label5.Text) * 510.0) / 2.0);
  1117. if (grayMin >= grayMax)
  1118. {
  1119. return;
  1120. }
  1121. if (updateThreePoints)
  1122. {
  1123. ucTrackBar1.Value1 = grayMin;
  1124. ucTrackBar1.Value3 = grayMax;
  1125. //ucTrackBar1.Value2 = (float)((grayMin + grayMax) / 2.0);
  1126. }
  1127. //gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  1128. double gamma = Math.Max(0.01, double.Parse(label7.Text));
  1129. //计算Value2
  1130. ucTrackBar1.Value2 = (float)Math.Max(grayMin, Math.Min(grayMax, Math.Pow(0.5, 1.0 / gamma) * (grayMax - grayMin) + grayMin));
  1131. ucTrackBar1.Refresh();
  1132. int lastY2 = histSize + 0;// histSize - 1;
  1133. for (int h = 0; h <= 256; h++)
  1134. {
  1135. if (h < grayMin)
  1136. {
  1137. points.Add(new OpenCvSharp.Point(h * 4, lastY2));
  1138. continue;
  1139. }
  1140. else if (h > grayMax)
  1141. {
  1142. lastY2 = -1;// 0;
  1143. points.Add(new OpenCvSharp.Point(h * 4, lastY2));
  1144. continue;
  1145. }
  1146. int lastY1 = (int)Math.Round((1.0 - Math.Pow((h - grayMin) * 1.0 / (grayMax - grayMin), gamma)) * (histSize + 1/*histSize - 1*/)) - 1;
  1147. lastY1 = Math.Min(lastY2, Math.Max(0, lastY1));
  1148. if (lastY2 == lastY1)
  1149. {
  1150. if (h == 0 || h == 256)
  1151. {
  1152. points.Add(new OpenCvSharp.Point(h * 4, lastY1));
  1153. }
  1154. }
  1155. else
  1156. {
  1157. points.Add(new OpenCvSharp.Point(h * 4, lastY1));
  1158. lastY2 = lastY1;
  1159. }
  1160. }
  1161. lastY2 = histSize + 0;// histSize - 1;
  1162. //将第一个点的位置设置最底部,保证曲线平滑性
  1163. //if (points[0].X > 4 && points[0].Y < lastY2)
  1164. //{
  1165. // points.Insert(0, new OpenCvSharp.Point(points[0].X - 4, lastY2));
  1166. //}
  1167. List<List<OpenCvSharp.Point>> pointsIn = new List<List<OpenCvSharp.Point>>()
  1168. {
  1169. points
  1170. };
  1171. //绘制折线
  1172. 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);
  1173. //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);
  1174. Mat A = new Mat(3 + 1, 1, MatType.CV_64FC1, new Scalar(0));
  1175. polynomial_curve_fit(points.ToArray(), 3, A);
  1176. List<OpenCvSharp.Point> points_fitted = new List<OpenCvSharp.Point>(); //std::vector<cv::Point> points_fitted;
  1177. List<double> dataFitted = new List<double>();
  1178. dataFitted.Add(A.At<double>(0, 0));
  1179. dataFitted.Add(A.At<double>(1, 0));
  1180. dataFitted.Add(A.At<double>(2, 0));
  1181. dataFitted.Add(A.At<double>(3, 0));
  1182. for (int x = 0; x < histSize + 1; x++)
  1183. {
  1184. if (x < grayMin * 4)
  1185. {
  1186. points_fitted.Add(new OpenCvSharp.Point(x, lastY2));
  1187. continue;
  1188. }
  1189. else if (x > grayMax * 4)
  1190. {
  1191. lastY2 = -1;// 0;
  1192. points_fitted.Add(new OpenCvSharp.Point(x, lastY2));
  1193. continue;
  1194. }
  1195. 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);
  1196. points_fitted.Add(new OpenCvSharp.Point(x, y));
  1197. }
  1198. //List<List<OpenCvSharp.Point>> points_fittedIn = new List<List<OpenCvSharp.Point>>()
  1199. //{
  1200. // points_fitted
  1201. //};
  1202. ////绘制折线
  1203. //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);
  1204. this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);
  1205. // //黄色线表示拟合后的曲线,成功
  1206. // 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);
  1207. // Cv2.ImShow("image", image);// cv::imshow("image", image);
  1208. //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  1209. }
  1210. /// <summary>
  1211. /// 根据亮度、对比度、gamma对图片进行处理
  1212. /// </summary>
  1213. private void scrollMethod()
  1214. {
  1215. if (this.AppWorkspace.ActiveDocumentWorkspace == null
  1216. /*|| !this.AppWorkspace.Widgets.HistogramDialog.Visible*/)
  1217. {
  1218. return;
  1219. }
  1220. Mat[] mats = Cv2.Split(this.AppWorkspace.ActiveDocumentWorkspace.OldMat);//一张图片,将panda拆分成3个图片装进mat
  1221. //根据亮度和对比度计算左右阈值
  1222. 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);
  1223. int grayMax = (int)((256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) - double.Parse(label5.Text) * 510.0) / 2.0);
  1224. if (grayMin >= grayMax)
  1225. {
  1226. return;
  1227. }
  1228. Mat dst = new Mat();
  1229. //如果是灰度化图片,则只需计算一个通道。对灰度值进行映射,BGR根据左右阈值做缩放操作
  1230. if (isGray)
  1231. {
  1232. Cv2.Min(mats[0], new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMax)), dst);
  1233. Cv2.Max(dst, new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMin)), dst);
  1234. Cv2.Normalize(dst, dst, 0, 255, NormTypes.MinMax);
  1235. }
  1236. else
  1237. {
  1238. for (int j = 0; j < oldHists.Length; j++)
  1239. {
  1240. Cv2.Min(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMax)), mats[j]);
  1241. Cv2.Max(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMin)), mats[j]);
  1242. //Cv2.Normalize(mats[j], mats[j], 0, 255, NormTypes.MinMax);
  1243. //for (int h=0; h< mats[j].Height; h++)
  1244. //{
  1245. // for (int w = 0; w < mats[j].Width; w++)
  1246. // {
  1247. // if(mats[j].At<byte>(h,w)<0) mats[j].Set<byte>(h, w, 0);
  1248. // if (mats[j].At<byte>(h, w) > 255) mats[j].Set<byte>(h, w, 255);
  1249. // }
  1250. //}
  1251. }
  1252. Cv2.Merge(mats, dst);
  1253. Cv2.Normalize(dst, dst, 0, 255, NormTypes.MinMax);
  1254. }
  1255. //灰度归一化
  1256. dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  1257. //gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  1258. Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7.Text)), dst);
  1259. dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
  1260. //Document document = Document.FromMat(dst/*this.AppWorkspace.ActiveDocumentWorkspace.OldMat*/);
  1261. Document document = Document.FromImage(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  1262. this.AppWorkspace.ActiveDocumentWorkspace.setDoc(document, false);
  1263. this.AppWorkspace.ActiveDocumentWorkspace.Refresh();
  1264. //this.AppWorkspace.ActiveDocumentWorkspace.CompositionSurface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  1265. #region 均衡化的方法备份
  1266. ////对灰度值进行映射(均衡化)
  1267. //float[] totalPoints = new float[] { oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows };
  1268. ////去掉黑色部分 和 白色部分
  1269. //for (int j = 0; j < oldHists.Length; j++)
  1270. //{
  1271. // for (int i = 0; i < grayMin; i++)
  1272. // {
  1273. // totalPoints[j] = totalPoints[j] - oldHists[j].At<float>(i);
  1274. // }
  1275. // for (int i = grayMax; i < oldHists[j].Rows; i++)
  1276. // {
  1277. // totalPoints[j] = totalPoints[j] - oldHists[j].At<float>(i);
  1278. // }
  1279. //}
  1280. //for (int j = 0; j < (isGray ? 1 : oldHists.Length); j++)
  1281. //{
  1282. // //计算灰度分布密度
  1283. // //List<float> ProbPixel = new List<float>();
  1284. // //计算累计直方图分布
  1285. // List<float> equalizeHists = new List<float>();
  1286. // Mat hist = oldHists[j];
  1287. // //计算累计直方图分布
  1288. // for (int i = 0; i < hist.Rows; ++i)
  1289. // {
  1290. // //去掉黑色部分 和 白色部分
  1291. // if (i < grayMin || i > grayMax)
  1292. // {
  1293. // if (i == 0)
  1294. // {
  1295. // equalizeHists.Add(0);
  1296. // }
  1297. // else
  1298. // {
  1299. // equalizeHists.Add(equalizeHists[i - 1]);
  1300. // }
  1301. // }
  1302. // else if (i == 0)
  1303. // {
  1304. // equalizeHists.Add((float)(hist.At<float>(i) / (totalPoints[j] * 1.0)));
  1305. // }
  1306. // else
  1307. // {
  1308. // equalizeHists.Add(equalizeHists[i - 1] + (float)(hist.At<float>(i) / (totalPoints[j] * 1.0)));
  1309. // }
  1310. // }
  1311. // //累计分布取整
  1312. // for (int i = 0; i < equalizeHists.Count; ++i)
  1313. // {
  1314. // float numHist = equalizeHists[i];
  1315. // equalizeHists[i] = Math.Min(255, (int)(numHist * 255.0 + 0.5));
  1316. // }
  1317. // for (int y = 0; y < h; ++y)
  1318. // //对灰度值进行映射,BGR根据左右阈值做缩放操作
  1319. // {
  1320. // byte* imageData = (byte*)(mats[j].Ptr(y));
  1321. // //对灰度值进行映射
  1322. // for (int x = 0; x < w; ++x)
  1323. // {
  1324. // int oldvalue = imageData[x];
  1325. // if (oldvalue < grayMin)
  1326. // {
  1327. // imageData[x] = 0;
  1328. // }
  1329. // else if (oldvalue > grayMax)
  1330. // {
  1331. // imageData[x] = 255;
  1332. // }
  1333. // else
  1334. // {
  1335. // imageData[x] = (byte)equalizeHists[oldvalue];
  1336. // }
  1337. // }
  1338. // }
  1339. //}
  1340. //Mat dst = new Mat();
  1341. ////灰度归一化
  1342. //if (isGray)
  1343. //{
  1344. // mats[0].ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  1345. //}
  1346. //else
  1347. //{
  1348. // Cv2.Merge(mats, dst);
  1349. // dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  1350. //}
  1351. ////gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  1352. //Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7.Text)), dst);
  1353. //dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
  1354. //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  1355. #endregion
  1356. }
  1357. /// <summary>
  1358. /// 拖动左侧三角形
  1359. /// </summary>
  1360. /// <param name="sender"></param>
  1361. /// <param name="e"></param>
  1362. private void ucTrackBar1_Value1Changed(object sender, EventArgs e)
  1363. {
  1364. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(ucTrackBar1.Value1, ucTrackBar1.Value3);
  1365. //计算对比度
  1366. label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
  1367. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  1368. //计算亮度
  1369. label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
  1370. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  1371. //备注:这里是可以优化用户体验的地方(避免操作事件引起多次计算发生)
  1372. //this.scrollMethod();
  1373. updateHistogramRect(false);
  1374. }
  1375. /// <summary>
  1376. /// 拖动中间三角形
  1377. /// </summary>
  1378. /// <param name="sender"></param>
  1379. /// <param name="e"></param>
  1380. private void ucTrackBar1_Value2Changed(object sender, EventArgs e)
  1381. {
  1382. //计算gamma值
  1383. double gamma = 1.0 / Math.Log((ucTrackBar1.Value2 - ucTrackBar1.Value1) / (ucTrackBar1.Value3 - ucTrackBar1.Value1), 0.5);
  1384. gamma = Math.Max(0.01, gamma);
  1385. this.trackBar3.Value = Math.Min(299, (int)(gamma * 100));//备注:需要与AxioVision进行比较效果,调试一致
  1386. label7.Text = gamma.ToString("f2");
  1387. //备注:这里是可以优化用户体验的地方(避免操作事件引起多次计算发生)
  1388. updateHistogramRect(false);
  1389. }
  1390. /// <summary>
  1391. /// 拖动右侧三角形
  1392. /// </summary>
  1393. /// <param name="sender"></param>
  1394. /// <param name="e"></param>
  1395. private void ucTrackBar1_Value3Changed(object sender, EventArgs e)
  1396. {
  1397. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(ucTrackBar1.Value1, ucTrackBar1.Value3);// this.getStartIndex(oldMat, oldHists, (float)numericUpDown1.Value);
  1398. //计算对比度
  1399. label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
  1400. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  1401. //计算亮度
  1402. label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
  1403. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  1404. //this.scrollMethod();
  1405. updateHistogramRect(false);
  1406. }
  1407. private void HistogramDialog_FormClosing(object sender, FormClosingEventArgs e)
  1408. {
  1409. this.AppWorkspace.toolBar.RefreshBtnSelect(false, "Histogram");
  1410. this.AppWorkspace.toolsPanel.RefreshBtnSelect(false, "Histogram");
  1411. }
  1412. }
  1413. }