DisplayCameraControl.cs 60 KB

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