DisplayControl.cs 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Data;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using PaintDotNet.Base.SettingModel;
  11. using OpenCvSharp;
  12. using PaintDotNet.CustomControl;
  13. using PaintDotNet.Camera;
  14. using OpenCvSharp.Extensions;
  15. using System.Threading;
  16. namespace PaintDotNet.Preview2
  17. {
  18. public class DisplayControl : UserControl
  19. {
  20. #region 初始化变量
  21. private AppWorkspace AppWorkspace;
  22. /// <summary>
  23. /// 一个矩阵数组,用来接收直方图,记得全部初始化
  24. /// </summary>
  25. Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };
  26. /// <summary>
  27. /// 相机采集的图像
  28. /// </summary>
  29. Mat OldMat;
  30. /// <summary>
  31. /// 灰度图
  32. /// </summary>
  33. private bool isGray = true;
  34. /// <summary>
  35. /// BGR线条颜色
  36. /// </summary>
  37. private Scalar[] color = new Scalar[] { new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255), new Scalar(0, 0, 255, 255) };
  38. #endregion
  39. #region 控件
  40. private Label label0005;
  41. /// <summary>
  42. /// 相机参数的Model
  43. /// </summary>
  44. private CameraParamModel m_cameraParamModel;
  45. private ICamera m_camera => CameraManager.CurrentCamera;
  46. private Label label7;
  47. private TriangleTrackBar trackBar3;
  48. private Label label6;
  49. private TriangleTrackBar trackBar2;
  50. private Label label5;
  51. private TriangleTrackBar trackBar1;
  52. private Label label3;
  53. private Label label2;
  54. private Label label1;
  55. public Button button5;
  56. public Button button4;
  57. private UCTrackBar ucTrackBar1;
  58. private SelectButton logButton;
  59. private SelectButton skipButton;
  60. private PictureBox pictureBox1;
  61. private GroupBox groupBox1;
  62. private Panel panel1;
  63. private Panel panel2;
  64. private TableLayoutPanel tableLayoutPanel1;
  65. private System.Threading.Timer m_aeTimer;
  66. #endregion
  67. public DisplayControl()
  68. {
  69. InitializeComponent();
  70. InitializeLanguageText();
  71. try
  72. {
  73. InitializeControlData();
  74. }
  75. catch { }
  76. }
  77. /// <summary>
  78. /// 设置直方图的图像
  79. /// </summary>
  80. /// <param name="mat"></param>
  81. /// <summary>
  82. /// 设置下拉等数据源
  83. /// </summary>
  84. private void InitializeControlData()
  85. {
  86. m_cameraParamModel = Startup.instance.cameraParamModel;
  87. if (m_camera.IsOpen())
  88. {
  89. m_aeTimer = new System.Threading.Timer(TimerUpdateHist, null, 500, 500);
  90. }
  91. ucTrackBar1.Value1 = m_camera.LeftLevel;
  92. ucTrackBar1.Value2 = (int)m_camera.Gamma;
  93. ucTrackBar1.Value3 = m_camera.RightLevel;
  94. trackBar1.Value = m_cameraParamModel.parame.Light;
  95. label5.Text = trackBar1.Value + "";
  96. trackBar2.Value = m_cameraParamModel.parame.Contrast;
  97. label6.Text = trackBar2.Value + "";
  98. trackBar3.Value = m_cameraParamModel.parame.Gamma;
  99. label7.Text = trackBar3.Value / 100f + "";
  100. }
  101. private void InitializeLanguageText()
  102. {
  103. this.label0005.Text = PdnResources.GetString("Menu.timeofexposure.text") + ":";
  104. this.label3.Text = PdnResources.GetString("Menu.Gammavalue.text") + ":";
  105. this.label2.Text = PdnResources.GetString("Menu.Contrast.text") + ":";
  106. this.label1.Text = PdnResources.GetString("Menu.luminance.text") + ":";
  107. this.button5.Text = PdnResources.GetString("Menu.Originalstate.text");
  108. this.button4.Text = PdnResources.GetString("Menu.Gammavalue.text") + "1.00";
  109. this.groupBox1.Text = PdnResources.GetString("Menu.Tools.Histogram.Text");
  110. }
  111. private void InitializeComponent()
  112. {
  113. this.label0005 = new System.Windows.Forms.Label();
  114. this.label7 = new System.Windows.Forms.Label();
  115. this.trackBar3 = new PaintDotNet.CustomControl.TriangleTrackBar();
  116. this.label6 = new System.Windows.Forms.Label();
  117. this.trackBar2 = new PaintDotNet.CustomControl.TriangleTrackBar();
  118. this.label5 = new System.Windows.Forms.Label();
  119. this.trackBar1 = new PaintDotNet.CustomControl.TriangleTrackBar();
  120. this.label3 = new System.Windows.Forms.Label();
  121. this.label2 = new System.Windows.Forms.Label();
  122. this.label1 = new System.Windows.Forms.Label();
  123. this.button5 = new System.Windows.Forms.Button();
  124. this.button4 = new System.Windows.Forms.Button();
  125. this.ucTrackBar1 = new PaintDotNet.CustomControl.UCTrackBar();
  126. this.logButton = new PaintDotNet.CustomControl.SelectButton();
  127. this.skipButton = new PaintDotNet.CustomControl.SelectButton();
  128. this.pictureBox1 = new System.Windows.Forms.PictureBox();
  129. this.groupBox1 = new System.Windows.Forms.GroupBox();
  130. this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
  131. this.panel2 = new System.Windows.Forms.Panel();
  132. this.panel1 = new System.Windows.Forms.Panel();
  133. ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
  134. this.groupBox1.SuspendLayout();
  135. this.tableLayoutPanel1.SuspendLayout();
  136. this.panel2.SuspendLayout();
  137. this.panel1.SuspendLayout();
  138. this.SuspendLayout();
  139. //
  140. // label0005
  141. //
  142. this.label0005.AutoSize = true;
  143. this.label0005.Location = new System.Drawing.Point(24, 39);
  144. this.label0005.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
  145. this.label0005.Name = "label0005";
  146. this.label0005.Size = new System.Drawing.Size(82, 15);
  147. this.label0005.TabIndex = 12;
  148. this.label0005.Text = "曝光时间:";
  149. //
  150. // label7
  151. //
  152. this.label7.AutoSize = true;
  153. this.label7.Location = new System.Drawing.Point(241, 83);
  154. this.label7.Margin = new System.Windows.Forms.Padding(0, 11, 0, 0);
  155. this.label7.Name = "label7";
  156. this.label7.Size = new System.Drawing.Size(29, 12);
  157. this.label7.TabIndex = 59;
  158. this.label7.Text = "1.00";
  159. //
  160. // trackBar3
  161. //
  162. this.trackBar3.Dock = System.Windows.Forms.DockStyle.Top;
  163. this.trackBar3.Location = new System.Drawing.Point(61, 75);
  164. this.trackBar3.Maximum = 255;
  165. this.trackBar3.Minimum = 64;
  166. this.trackBar3.Name = "trackBar3";
  167. this.trackBar3.Size = new System.Drawing.Size(177, 28);
  168. this.trackBar3.TabIndex = 58;
  169. this.trackBar3.Value = 100;
  170. this.trackBar3.TrackBarScroll += new System.EventHandler(this.trackBar3_Scroll);
  171. //
  172. // label6
  173. //
  174. this.label6.AutoSize = true;
  175. this.label6.Location = new System.Drawing.Point(241, 49);
  176. this.label6.Margin = new System.Windows.Forms.Padding(0, 11, 0, 0);
  177. this.label6.Name = "label6";
  178. this.label6.Size = new System.Drawing.Size(29, 12);
  179. this.label6.TabIndex = 57;
  180. this.label6.Text = "1.00";
  181. //
  182. // trackBar2
  183. //
  184. this.trackBar2.Dock = System.Windows.Forms.DockStyle.Top;
  185. this.trackBar2.Location = new System.Drawing.Point(61, 41);
  186. this.trackBar2.Maximum = 63;
  187. this.trackBar2.Minimum = 0;
  188. this.trackBar2.Name = "trackBar2";
  189. this.trackBar2.Size = new System.Drawing.Size(177, 28);
  190. this.trackBar2.TabIndex = 56;
  191. this.trackBar2.Value = 63;
  192. this.trackBar2.TrackBarScroll += new System.EventHandler(this.trackBar2_Scroll);
  193. //
  194. // label5
  195. //
  196. this.label5.AutoSize = true;
  197. this.label5.Location = new System.Drawing.Point(241, 15);
  198. this.label5.Margin = new System.Windows.Forms.Padding(0, 11, 0, 0);
  199. this.label5.Name = "label5";
  200. this.label5.Size = new System.Drawing.Size(29, 12);
  201. this.label5.TabIndex = 55;
  202. this.label5.Text = "-0.5";
  203. //
  204. // trackBar1
  205. //
  206. this.trackBar1.Dock = System.Windows.Forms.DockStyle.Top;
  207. this.trackBar1.Location = new System.Drawing.Point(61, 7);
  208. this.trackBar1.Maximum = 255;
  209. this.trackBar1.Minimum = 0;
  210. this.trackBar1.Name = "trackBar1";
  211. this.trackBar1.Size = new System.Drawing.Size(177, 28);
  212. this.trackBar1.TabIndex = 54;
  213. this.trackBar1.Value = 0;
  214. this.trackBar1.TrackBarScroll += new System.EventHandler(this.Light_Scroll);
  215. //
  216. // label3
  217. //
  218. this.label3.AutoSize = true;
  219. this.label3.Location = new System.Drawing.Point(4, 83);
  220. this.label3.Margin = new System.Windows.Forms.Padding(0, 11, 0, 0);
  221. this.label3.Name = "label3";
  222. this.label3.Size = new System.Drawing.Size(53, 12);
  223. this.label3.TabIndex = 51;
  224. this.label3.Text = "伽马值:";
  225. //
  226. // label2
  227. //
  228. this.label2.AutoSize = true;
  229. this.label2.Location = new System.Drawing.Point(4, 49);
  230. this.label2.Margin = new System.Windows.Forms.Padding(0, 11, 0, 0);
  231. this.label2.Name = "label2";
  232. this.label2.Size = new System.Drawing.Size(53, 12);
  233. this.label2.TabIndex = 50;
  234. this.label2.Text = "对比度:";
  235. //
  236. // label1
  237. //
  238. this.label1.AutoSize = true;
  239. this.label1.Location = new System.Drawing.Point(4, 15);
  240. this.label1.Margin = new System.Windows.Forms.Padding(0, 11, 0, 0);
  241. this.label1.Name = "label1";
  242. this.label1.Size = new System.Drawing.Size(41, 12);
  243. this.label1.TabIndex = 49;
  244. this.label1.Text = "亮度:";
  245. //
  246. // button5
  247. //
  248. this.button5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
  249. this.button5.Location = new System.Drawing.Point(87, 288);
  250. this.button5.Name = "button5";
  251. this.button5.Size = new System.Drawing.Size(75, 23);
  252. this.button5.TabIndex = 48;
  253. this.button5.Text = "原始状态";
  254. this.button5.UseVisualStyleBackColor = true;
  255. this.button5.Click += new System.EventHandler(this.button5_Click);
  256. //
  257. // button4
  258. //
  259. this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
  260. this.button4.Location = new System.Drawing.Point(9, 288);
  261. this.button4.Name = "button4";
  262. this.button4.Size = new System.Drawing.Size(75, 23);
  263. this.button4.TabIndex = 47;
  264. this.button4.Text = "伽马值1.00";
  265. this.button4.UseVisualStyleBackColor = true;
  266. this.button4.Click += new System.EventHandler(this.button4_Click);
  267. //
  268. // ucTrackBar1
  269. //
  270. this.ucTrackBar1.DcimalDigits = 0;
  271. this.ucTrackBar1.Dock = System.Windows.Forms.DockStyle.Top;
  272. this.ucTrackBar1.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(77)))), ((int)(((byte)(59)))));
  273. this.ucTrackBar1.LineWidth = 8F;
  274. this.ucTrackBar1.Location = new System.Drawing.Point(3, 131);
  275. this.ucTrackBar1.MaxValue = 255F;
  276. this.ucTrackBar1.MinValue = 0F;
  277. this.ucTrackBar1.Name = "ucTrackBar1";
  278. this.ucTrackBar1.Size = new System.Drawing.Size(282, 15);
  279. this.ucTrackBar1.TabIndex = 44;
  280. this.ucTrackBar1.Text = "ucTrackBar1";
  281. this.ucTrackBar1.Value1 = 0F;
  282. this.ucTrackBar1.Value2 = 127F;
  283. this.ucTrackBar1.Value3 = 255F;
  284. this.ucTrackBar1.Value1Changed += new System.EventHandler(this.LeftLevelChanged);
  285. this.ucTrackBar1.Value2Changed += new System.EventHandler(this.ucTrackBar1_Value2Changed);
  286. this.ucTrackBar1.Value3Changed += new System.EventHandler(this.RightLevelChanged);
  287. //
  288. // logButton
  289. //
  290. this.logButton.BackColor = System.Drawing.SystemColors.ControlDark;
  291. this.logButton.BtnSelect = false;
  292. this.logButton.BtnText = "log";
  293. this.logButton.Location = new System.Drawing.Point(69, 1);
  294. this.logButton.Name = "logButton";
  295. this.logButton.Size = new System.Drawing.Size(41, 21);
  296. this.logButton.TabIndex = 43;
  297. this.logButton.Click += new System.EventHandler(this.logButton_Click);
  298. //
  299. // skipButton
  300. //
  301. this.skipButton.BackColor = System.Drawing.SystemColors.ControlDark;
  302. this.skipButton.BtnSelect = false;
  303. this.skipButton.BtnText = "skip";
  304. this.skipButton.Location = new System.Drawing.Point(166, 0);
  305. this.skipButton.Name = "skipButton";
  306. this.skipButton.Size = new System.Drawing.Size(41, 21);
  307. this.skipButton.TabIndex = 42;
  308. this.skipButton.Click += new System.EventHandler(this.skipButton_Click);
  309. //
  310. // pictureBox1
  311. //
  312. this.pictureBox1.BackColor = System.Drawing.Color.White;
  313. this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
  314. this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
  315. this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
  316. this.pictureBox1.Location = new System.Drawing.Point(7, 0);
  317. this.pictureBox1.Name = "pictureBox1";
  318. this.pictureBox1.Size = new System.Drawing.Size(268, 114);
  319. this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
  320. this.pictureBox1.TabIndex = 41;
  321. this.pictureBox1.TabStop = false;
  322. //
  323. // groupBox1
  324. //
  325. this.groupBox1.Controls.Add(this.tableLayoutPanel1);
  326. this.groupBox1.Controls.Add(this.panel2);
  327. this.groupBox1.Controls.Add(this.button5);
  328. this.groupBox1.Controls.Add(this.button4);
  329. this.groupBox1.Controls.Add(this.ucTrackBar1);
  330. this.groupBox1.Controls.Add(this.panel1);
  331. this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill;
  332. this.groupBox1.Location = new System.Drawing.Point(0, 6);
  333. this.groupBox1.Name = "groupBox1";
  334. this.groupBox1.Size = new System.Drawing.Size(288, 322);
  335. this.groupBox1.TabIndex = 60;
  336. this.groupBox1.TabStop = false;
  337. this.groupBox1.Text = "直方图";
  338. //
  339. // tableLayoutPanel1
  340. //
  341. this.tableLayoutPanel1.ColumnCount = 3;
  342. this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 54F));
  343. this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
  344. this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 37F));
  345. this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);
  346. this.tableLayoutPanel1.Controls.Add(this.label2, 0, 1);
  347. this.tableLayoutPanel1.Controls.Add(this.label3, 0, 2);
  348. this.tableLayoutPanel1.Controls.Add(this.label5, 2, 0);
  349. this.tableLayoutPanel1.Controls.Add(this.label6, 2, 1);
  350. this.tableLayoutPanel1.Controls.Add(this.label7, 2, 2);
  351. this.tableLayoutPanel1.Controls.Add(this.trackBar1, 1, 0);
  352. this.tableLayoutPanel1.Controls.Add(this.trackBar2, 1, 1);
  353. this.tableLayoutPanel1.Controls.Add(this.trackBar3, 1, 2);
  354. this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top;
  355. this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 168);
  356. this.tableLayoutPanel1.Name = "tableLayoutPanel1";
  357. this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(4);
  358. this.tableLayoutPanel1.RowCount = 3;
  359. this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
  360. this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
  361. this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
  362. this.tableLayoutPanel1.Size = new System.Drawing.Size(282, 110);
  363. this.tableLayoutPanel1.TabIndex = 61;
  364. //
  365. // panel2
  366. //
  367. this.panel2.Controls.Add(this.logButton);
  368. this.panel2.Controls.Add(this.skipButton);
  369. this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
  370. this.panel2.Location = new System.Drawing.Point(3, 146);
  371. this.panel2.Name = "panel2";
  372. this.panel2.Size = new System.Drawing.Size(282, 22);
  373. this.panel2.TabIndex = 60;
  374. //
  375. // panel1
  376. //
  377. this.panel1.Controls.Add(this.pictureBox1);
  378. this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
  379. this.panel1.Location = new System.Drawing.Point(3, 17);
  380. this.panel1.Name = "panel1";
  381. this.panel1.Padding = new System.Windows.Forms.Padding(7, 0, 7, 0);
  382. this.panel1.Size = new System.Drawing.Size(282, 114);
  383. this.panel1.TabIndex = 0;
  384. //
  385. // DisplayControl
  386. //
  387. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
  388. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  389. this.Controls.Add(this.groupBox1);
  390. this.Name = "DisplayControl";
  391. this.Padding = new System.Windows.Forms.Padding(0, 6, 0, 0);
  392. this.Size = new System.Drawing.Size(288, 328);
  393. ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
  394. this.groupBox1.ResumeLayout(false);
  395. this.tableLayoutPanel1.ResumeLayout(false);
  396. this.tableLayoutPanel1.PerformLayout();
  397. this.panel2.ResumeLayout(false);
  398. this.panel1.ResumeLayout(false);
  399. this.ResumeLayout(false);
  400. }
  401. /// <summary>
  402. /// 刷新直方图
  403. /// </summary>
  404. /// <param name="e"></param>
  405. public void TimerUpdateHist(object e)
  406. {
  407. try
  408. {
  409. if (this.Parent == null)
  410. {
  411. m_aeTimer.Dispose();
  412. return;
  413. }
  414. if (!this.Visible)
  415. return;
  416. CameraManager.Shoot((bitmap) =>
  417. {
  418. try
  419. {
  420. if (bitmap == null) return;
  421. var mat = PaintDotNet.Camera.Tools.ToMat(bitmap);
  422. updateHistImg(mat);
  423. updateHistogramRect(false);
  424. }
  425. catch { }
  426. });
  427. }
  428. catch
  429. {
  430. m_aeTimer.Dispose();
  431. }
  432. }
  433. public unsafe void updateHistImg(OpenCvSharp.Mat mat)
  434. {
  435. OldMat = mat;
  436. isGray = true;
  437. if (this.OldMat == null) return;
  438. Mat[] mats = Cv2.Split(this.OldMat);//一张图片,将panda拆分成3个图片装进mat
  439. Mat[] mats0 = new Mat[] { mats[0] };//B
  440. Mat[] mats1;
  441. Mat[] mats2;
  442. if (mats.Length > 1)
  443. {
  444. isGray = false;
  445. mats1 = new Mat[] { mats[1] };//G
  446. mats2 = new Mat[] { mats[2] };//R
  447. }
  448. else
  449. {
  450. mats1 = new Mat[] { mats[0] };//G
  451. mats2 = new Mat[] { mats[0] };//R
  452. }
  453. int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  454. int[] channels1 = new int[] { 0 };
  455. int[] channels2 = new int[] { 0 };
  456. int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  457. Rangef[] range = new Rangef[1];//一个通道,范围
  458. range[0] = new Rangef(0.0F, 256.0F);
  459. //range[0].Start = 0.0F;//从0开始(含)
  460. //range[0].End = 256.0F;//到256结束(不含)
  461. Mat mask = new Mat();//不做掩码
  462. Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  463. Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  464. Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  465. var hists = oldHists;
  466. if (logButton.BtnSelect)
  467. {
  468. //取对数
  469. for (int j = 0; j < hists.Length; j++)
  470. {
  471. List<float> ProbPixel = new List<float>();
  472. for (int i = 0; i < hists[j].Rows; i++)
  473. {
  474. if (((float*)hists[j].Ptr(0))[i] == 0)
  475. {
  476. ((float*)hists[j].Ptr(0))[i] = ((float*)hists[j].Ptr(0))[i];
  477. ProbPixel.Add(0);
  478. }
  479. else
  480. {
  481. ((float*)hists[j].Ptr(0))[i] = (float)Math.Log10(((float*)hists[j].Ptr(0))[i]/* + 9*/);
  482. ProbPixel.Add(1);
  483. }
  484. }
  485. double max1jVal = 0;
  486. double min1jVal = 0;
  487. //找到直方图中的最大值和最小值
  488. Cv2.MinMaxLoc(hists[j], out min1jVal, out max1jVal);
  489. if (min1jVal >= max1jVal)
  490. {
  491. continue;
  492. }
  493. //归一化到0~255,并根据AxioVision添加偏置值
  494. for (int i = 0; i < hists[j].Rows; i++)
  495. {
  496. ((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);
  497. }
  498. }
  499. }
  500. if (skipButton.BtnSelect)
  501. {
  502. //去掉黑色部分 和 白色部分
  503. for (int j = 0; j < hists.Length; j++)
  504. {
  505. ((float*)hists[j].Ptr(0))[0] = 0;
  506. ((float*)hists[j].Ptr(0))[255] = 0;
  507. }
  508. }
  509. double max2Val = 0;
  510. double max1Val = 0;
  511. double max0Val = 0;
  512. double minVal = 0;
  513. //为了更好显示直方图细节,使用4倍尺寸绘制直方图
  514. int histSize = hists[0].Rows * 4;
  515. Mat histImg = new Mat(histSize, histSize, MatType.CV_8UC3, new Scalar(255, 255, 255));
  516. //找到直方图中的最大值和最小值
  517. Cv2.MinMaxLoc(hists[2], out minVal, out max2Val);
  518. Cv2.MinMaxLoc(hists[1], out minVal, out max1Val);
  519. Cv2.MinMaxLoc(hists[0], out minVal, out max0Val);
  520. double maxVal = Math.Max(max2Val, Math.Max(max0Val, max1Val));
  521. if (maxVal < 1)
  522. return;
  523. // 设置最大峰值为图像高度的90%
  524. double hpt = 0.9 * histSize;
  525. //灰度图的显示直方图较为简单,显示一个通道即可
  526. if (isGray)
  527. {
  528. Mat hist = hists[0];
  529. int lastY2 = histSize - 1;
  530. for (int h = 0; h < hists[0].Rows; h++)
  531. {
  532. int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  533. int lastY1 = lastY2;
  534. lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  535. if (lastY2 < lastY1)
  536. {
  537. 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);
  538. }
  539. else
  540. {
  541. 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);
  542. }
  543. }
  544. }
  545. //彩度图显示BGR三个通道的直方图
  546. else
  547. {
  548. int lineWidth = 2;
  549. for (int j = hists.Length - 1; j >= 0; j--)
  550. {
  551. Mat hist = hists[j];
  552. int lastY2 = histSize - 1;
  553. for (int h = 0; h < hists[0].Rows; h++)
  554. {
  555. int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  556. int lastY1 = lastY2;
  557. lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  558. if (h > 0)
  559. {
  560. //显示0.5位置的直方图,这样与AxioVision效果更加近似
  561. int lasty12 = (lastY1 + lastY2) / 2;
  562. if (lasty12 < lastY1)
  563. {
  564. 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);
  565. }
  566. else
  567. {
  568. 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*/);
  569. }
  570. if (lastY2 < lasty12)
  571. {
  572. Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lasty12 - 2)), color[j], lineWidth, LineTypes.Link4);
  573. }
  574. else
  575. {
  576. 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*/);
  577. }
  578. }
  579. else
  580. {
  581. //灰度值为0的线的绘制
  582. if (lastY2 < lastY1)
  583. {
  584. Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
  585. }
  586. else
  587. {
  588. 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*/);
  589. }
  590. }
  591. }
  592. }
  593. }
  594. this.pictureBox1.BackgroundImage = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  595. }
  596. /// <summary>
  597. /// 伽马1.00
  598. /// 需要调整直线的弧度
  599. /// 直方图曲线根据伽马值进行变化
  600. /// </summary>
  601. /// <param name="sender"></param>
  602. /// <param name="e"></param>
  603. private void button4_Click(object sender, EventArgs e)
  604. {
  605. this.trackBar3.Value = 100;
  606. trackBar3_Scroll(null, null);
  607. }
  608. /// <summary>
  609. /// 原始状态
  610. /// </summary>
  611. private void button5_Click(object sender, EventArgs e)
  612. {
  613. this.trackBar1.Value = 64;
  614. Light_Scroll(null, null);
  615. this.trackBar2.Value = 33;
  616. trackBar2_Scroll(null, null);
  617. this.trackBar3.Value = 100;
  618. trackBar3_Scroll(null, null);
  619. m_camera.LeftLevel = 0;
  620. m_camera.RightLevel = 255;
  621. ucTrackBar1.Value1 = 0;
  622. ucTrackBar1.Value3 = 255;
  623. }
  624. /// <summary>
  625. /// skip按钮
  626. /// 显示直方图时,忽略黑色的灰度或颜色值。
  627. /// 这使您可以为背景为黑色的图像实现有意义的直方图显示。
  628. /// </summary>
  629. private void skipButton_Click(object sender, EventArgs e)
  630. {
  631. if (this.OldMat == null)
  632. {
  633. return;
  634. }
  635. //设置按钮的选中/非选择的状态
  636. skipButton.BtnSelect = !skipButton.BtnSelect;
  637. }
  638. /// <summary>
  639. /// log按钮
  640. /// 以对数比例显示直方图
  641. /// </summary>
  642. /// <param name="sender"></param>
  643. /// <param name="e"></param>
  644. private void logButton_Click(object sender, EventArgs e)
  645. {
  646. if (this.OldMat == null)
  647. {
  648. return;
  649. }
  650. //设置按钮的选中/非选择的状态
  651. logButton.BtnSelect = !logButton.BtnSelect;
  652. }
  653. /// <summary>
  654. /// 亮度改变
  655. /// </summary>
  656. /// <param name="sender"></param>
  657. /// <param name="e"></param>
  658. private void Light_Scroll(object sender, EventArgs e)
  659. {
  660. var value = trackBar1.Value;
  661. m_camera.Light = value;
  662. label5.Text = value + "";
  663. }
  664. /// <summary>
  665. /// 对比度改变
  666. /// </summary>
  667. /// <param name="sender"></param>
  668. /// <param name="e"></param>
  669. private void trackBar2_Scroll(object sender, EventArgs e)
  670. {
  671. var value = trackBar2.Value;
  672. label6.Text = value + "";
  673. m_camera.Contrast = value;
  674. }
  675. /// <summary>
  676. /// gamma改变
  677. /// gamma值小于1时,会拉伸图像中灰度级较低的区域,同时会压缩灰度级较高的部分
  678. /// gamma值大于1时,会拉伸图像中灰度级较高的区域,同时会压缩灰度级较低的部分
  679. /// </summary>
  680. /// <param name="sender"></param>
  681. /// <param name="e"></param>
  682. private void trackBar3_Scroll(object sender, EventArgs e)
  683. {
  684. var value = trackBar3.Value;
  685. label7.Text = (value / 100.0).ToString("f2");
  686. m_camera.Gamma = value;
  687. ucTrackBar1.Value2 = value;
  688. }
  689. /// <summary>
  690. /// 将拟合点绘制到空白图上
  691. /// //原文链接:https://blog.csdn.net/guduruyu/article/details/72866144
  692. /// </summary>
  693. /// <param name="key_point">拟合点</param>
  694. /// <param name="n">拟合矩阵的??数量</param>
  695. /// <param name="A">空白图</param>
  696. /// <returns></returns>
  697. private unsafe bool polynomial_curve_fit(OpenCvSharp.Point[] key_point, int n, Mat A)
  698. {
  699. //Number of key points
  700. int N = key_point.Length;
  701. //构造矩阵X
  702. 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);
  703. for (int i = 0; i < n + 1; i++)
  704. {
  705. for (int j = 0; j < n + 1; j++)
  706. {
  707. ((double*)X.Ptr(i))[j] = 0;//111
  708. for (int k = 0; k < N; k++)
  709. {
  710. ((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);
  711. }
  712. }
  713. }
  714. //构造矩阵Y
  715. Mat Y = new Mat(n + 1, 1, MatType.CV_64FC1, new Scalar(0));// cv::Mat Y = cv::Mat::zeros(n + 1, 1, CV_64FC1);
  716. for (int i = 0; i < n + 1; i++)
  717. {
  718. ((double*)Y.Ptr(i))[0] = 0;//111
  719. for (int k = 0; k < N; k++)
  720. {
  721. ((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;
  722. }
  723. }
  724. //A = new Mat(n + 1, 1, MatType.CV_64FC1, new Scalar(0));// A = cv::Mat::zeros(n + 1, 1, CV_64FC1);
  725. //List<double> dataFitted = new List<double>();
  726. //dataFitted.Add(Y.At<double>(0, 0));
  727. //dataFitted.Add(Y.At<double>(1, 0));
  728. //dataFitted.Add(Y.At<double>(2, 0));
  729. //dataFitted.Add(Y.At<double>(3, 0));
  730. //for (int i = 0; i < n + 1; i++)
  731. //{
  732. // for (int j = 0; j < n + 1; j++)
  733. // {
  734. // dataFitted.Add(X.At<double>(i, j));
  735. // }
  736. //}
  737. //求解矩阵A
  738. Cv2.Solve(X, Y, A, DecompTypes.LU);//Cv2.Solve(X, Y, A, DecompTypes.LU); cv::solve(X, Y, A, cv::DECOMP_LU);
  739. //dataFitted.Add(A.At<double>(0, 0));
  740. //dataFitted.Add(A.At<double>(1, 0));
  741. //dataFitted.Add(A.At<double>(2, 0));
  742. //dataFitted.Add(A.At<double>(3, 0));
  743. return true;
  744. }
  745. /// <summary>
  746. /// 通过颜色通道去除像素点的千分比计算有效阈值
  747. /// </summary>
  748. /// <param name="hists"></param>
  749. /// <param name="percentValue"></param>
  750. /// <returns></returns>
  751. private OpenCvSharp.Point getStartIndex(Mat mat, float percentValue)
  752. {
  753. if (mat.Channels() == 3)
  754. {
  755. Cv2.CvtColor(mat, mat, ColorConversionCodes.RGB2GRAY);
  756. }
  757. Mat mask = new Mat();//不做掩码
  758. Mat[] mats = Cv2.Split(mat);//一张图片,将panda拆分成3个图片装进mat
  759. Mat[] mats0 = new Mat[] { mats[0] };//B
  760. int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  761. int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  762. Rangef[] range = new Rangef[1];//一个通道,范围
  763. range[0] = new Rangef(0.0F, 256.0F);
  764. //range[0].Start = 0.0F;//从0开始(含)
  765. //range[0].End = 256.0F;//到256结束(不含)
  766. Mat hist = new Mat();
  767. Cv2.CalcHist(mats0, channels0, mask, hist, 1, histsize, range);//对被拆分的图片单独进行计算
  768. return this.getStartRange(hist, percentValue);
  769. }
  770. private OpenCvSharp.Point getStartRange(Mat matGray, float percentValue)
  771. {
  772. if (this.OldMat == null)
  773. {
  774. return new OpenCvSharp.Point(1, 254); ;
  775. }
  776. //计算灰度分布密度
  777. float totalPoints = this.OldMat.Cols * this.OldMat.Rows;
  778. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(0, matGray.Rows);
  779. bool foundStartTag = false;
  780. bool foundEndTag = false;
  781. //根据累计直方图分布计算左右阈值
  782. float equalizeHists = 0;
  783. for (int i = 0; i < matGray.Rows; ++i)
  784. {
  785. equalizeHists += ((float)(matGray.At<float>(i) / (totalPoints * 1.0))) * 1000;
  786. if (!foundStartTag && equalizeHists > percentValue)
  787. {
  788. foundStartTag = true;
  789. startIndex.X = i;
  790. }
  791. else if (equalizeHists >= 1000 - percentValue)
  792. {
  793. foundEndTag = true;
  794. startIndex.Y = i;
  795. }
  796. if (foundStartTag && foundEndTag)
  797. break;
  798. }
  799. startIndex.Y = Math.Min(255 - 1, startIndex.Y);
  800. startIndex.X = Math.Max(startIndex.X, 1);
  801. startIndex.Y = Math.Max(startIndex.X + 1, startIndex.Y);
  802. return startIndex;
  803. }
  804. /// <summary>
  805. /// 更新直方图特征曲线
  806. /// </summary>
  807. /// <param name="updateThreePoints">是否需要更新三个控制点的位置</param>
  808. private void updateHistogramRect(bool updateThreePoints)
  809. {
  810. //为了更好显示直方图细节,使用4倍尺寸绘制直方图
  811. int histSize = 256/*oldHists[0].Rows*/ * 4;
  812. //创建用于绘制的深蓝色背景图像
  813. Mat image = new Mat(histSize, histSize, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  814. //输入拟合点
  815. List<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();
  816. //根据亮度和对比度计算左右阈值
  817. int grayMin = (int)ucTrackBar1.Value1;
  818. int grayMax = (int)ucTrackBar1.Value3;
  819. if (grayMin >= grayMax)
  820. {
  821. return;
  822. }
  823. if (updateThreePoints)
  824. {
  825. ucTrackBar1.Value1 = grayMin;
  826. ucTrackBar1.Value3 = grayMax;
  827. //ucTrackBar1.Value2 = (float)((grayMin + grayMax) / 2.0);
  828. }
  829. if (this.IsDisposed)
  830. return;
  831. //gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  832. double gamma = Math.Max(0.01, double.Parse(label7.Text));
  833. //计算Value2
  834. // ucTrackBar1.Value2 = (float)Math.Max(grayMin, Math.Min(grayMax, Math.Pow(0.5, 1.0 / gamma) * (grayMax - grayMin) + grayMin));
  835. this.Invoke(new Action(() =>
  836. {
  837. ucTrackBar1.Refresh();
  838. }));
  839. int lastY2 = histSize + 0;// histSize - 1;
  840. for (int h = 0; h <= 256; h++)
  841. {
  842. if (h < grayMin)
  843. {
  844. points.Add(new OpenCvSharp.Point(h * 4, lastY2));
  845. continue;
  846. }
  847. else if (h > grayMax)
  848. {
  849. lastY2 = -1;// 0;
  850. points.Add(new OpenCvSharp.Point(h * 4, lastY2));
  851. continue;
  852. }
  853. int lastY1 = (int)Math.Round((1.0 - Math.Pow((h - grayMin) * 1.0 / (grayMax - grayMin), gamma)) * (histSize + 1/*histSize - 1*/)) - 1;
  854. lastY1 = Math.Min(lastY2, Math.Max(0, lastY1));
  855. if (lastY2 == lastY1)
  856. {
  857. if (h == 0 || h == 256)
  858. {
  859. points.Add(new OpenCvSharp.Point(h * 4, lastY1));
  860. }
  861. }
  862. else
  863. {
  864. points.Add(new OpenCvSharp.Point(h * 4, lastY1));
  865. lastY2 = lastY1;
  866. }
  867. }
  868. lastY2 = histSize + 0;// histSize - 1;
  869. //将第一个点的位置设置最底部,保证曲线平滑性
  870. //if (points[0].X > 4 && points[0].Y < lastY2)
  871. //{
  872. // points.Insert(0, new OpenCvSharp.Point(points[0].X - 4, lastY2));
  873. //}
  874. List<List<OpenCvSharp.Point>> pointsIn = new List<List<OpenCvSharp.Point>>()
  875. {
  876. points
  877. };
  878. //绘制折线
  879. 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);
  880. //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);
  881. Mat A = new Mat(3 + 1, 1, MatType.CV_64FC1, new Scalar(0));
  882. polynomial_curve_fit(points.ToArray(), 3, A);
  883. this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);
  884. }
  885. /// <summary>
  886. /// 拖动左侧三角形
  887. /// </summary>
  888. /// <param name="sender"></param>
  889. /// <param name="e"></param>
  890. private void LeftLevelChanged(object sender, EventArgs e)
  891. {
  892. var valueL = ucTrackBar1.Value1;
  893. var valueR = ucTrackBar1.Value3;
  894. if (valueR - valueL < 1)
  895. {
  896. valueL = valueR - 1;
  897. ucTrackBar1.Value1 = valueL;
  898. }
  899. m_camera.LeftLevel = (int)valueL;
  900. }
  901. /// <summary>
  902. /// 拖动右侧三角形
  903. /// </summary>
  904. /// <param name="sender"></param>
  905. /// <param name="e"></param>
  906. private void RightLevelChanged(object sender, EventArgs e)
  907. {
  908. var valueL = ucTrackBar1.Value1;
  909. var valueR = ucTrackBar1.Value3;
  910. if (valueR - valueL < 1)
  911. {
  912. valueR = valueL + 1;
  913. ucTrackBar1.Value3 = valueR;
  914. }
  915. m_camera.RightLevel = (int)valueR;
  916. }
  917. private void ucTrackBar1_Value2Changed(object sender, EventArgs e)
  918. {
  919. if (ucTrackBar1.Value2 < 64)
  920. {
  921. ucTrackBar1.Value2 = 64;
  922. }
  923. var value = (int)ucTrackBar1.Value2;
  924. trackBar3.Value = value;
  925. label7.Text = (value / 100.0).ToString("f2");
  926. m_camera.Gamma = value;
  927. }
  928. protected override void Dispose(bool disposing)
  929. {
  930. m_aeTimer?.Dispose();
  931. base.Dispose(disposing);
  932. }
  933. }
  934. }