DisplayCameraControl.cs 102 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275
  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 TUCAMAPI;
  12. using TUCamera;
  13. using OpenCvSharp;
  14. using PaintDotNet.CustomControl;
  15. namespace PaintDotNet.Setting.LabelComponent
  16. {
  17. public class DisplayCameraControl : UserControl
  18. {
  19. #region 初始化变量
  20. private AppWorkspace AppWorkspace;
  21. /// <summary>
  22. /// 一个矩阵数组,用来接收直方图,记得全部初始化
  23. /// </summary>
  24. Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };
  25. /// <summary>
  26. /// 相机采集的图像
  27. /// </summary>
  28. Mat OldMat;
  29. /// <summary>
  30. /// 灰度图
  31. /// </summary>
  32. private bool isGray = true;
  33. /// <summary>
  34. /// BGR线条颜色
  35. /// </summary>
  36. private Scalar[] color = new Scalar[] { new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255), new Scalar(0, 0, 255, 255) };
  37. public int trackBar1Value = -50;//亮度
  38. public int trackBar2Value = 100;//对比度
  39. public int trackBar3Value = 100;//gamma值
  40. #endregion
  41. #region 控件
  42. private Label label0005;
  43. /// <summary>
  44. /// 相机参数的Model
  45. /// </summary>
  46. private CameraParamModel m_cameraParamModel;
  47. private bool m_immediately;
  48. private TUCamera.TUCamera m_camera;
  49. private Label label7;
  50. private TriangleTrackBar trackBar3;
  51. private Label label6;
  52. private TriangleTrackBar trackBar2;
  53. private Label label5;
  54. private TriangleTrackBar trackBar1;
  55. private Label label4;
  56. private NumericUpDown numericUpDown1;
  57. private Label label3;
  58. private Label label2;
  59. private Label label1;
  60. public Button button5;
  61. public Button button4;
  62. public Button button3;
  63. public Button button2;
  64. private UCTrackBar ucTrackBar1;
  65. private SelectButton logButton;
  66. private SelectButton skipButton;
  67. private PictureBox pictureBox1;
  68. private System.Timers.Timer m_aeTimer;
  69. #endregion
  70. public DisplayCameraControl(CameraParamModel model, bool immediately)
  71. {
  72. m_cameraParamModel = model;
  73. m_immediately = immediately;
  74. m_camera = TUCameraManager.GetInstance().GetCurrentCamera();
  75. InitializeComponent();
  76. InitializeLanguageText();
  77. InitColorAdjustRange();
  78. InitializeControlData();
  79. }
  80. /// <summary>
  81. /// 设置直方图的图像
  82. /// </summary>
  83. /// <param name="mat"></param>
  84. public void resetMat(OpenCvSharp.Mat mat)
  85. {
  86. OldMat = mat;
  87. if (this.OldMat == null)
  88. {
  89. isGray = true;
  90. return;
  91. }
  92. isGray = true;
  93. Mat[] mats = Cv2.Split(this.OldMat);//一张图片,将panda拆分成3个图片装进mat
  94. Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  95. Mat[] mats1;
  96. if (mats.Length < 2)
  97. mats1 = new Mat[] { mats[0] };//panda的第二个通道,也就是G
  98. else
  99. mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  100. Mat[] mats2;
  101. if (mats.Length < 3)
  102. mats2 = new Mat[] { mats[0] };//panda的第三个通道,也就是R
  103. else
  104. mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  105. int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  106. int[] channels1 = new int[] { 0 };
  107. int[] channels2 = new int[] { 0 };
  108. int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  109. Rangef[] range = new Rangef[1];//一个通道,范围
  110. range[0].Start = 0.0F;//从0开始(含)
  111. range[0].End = 256.0F;//到256结束(不含)
  112. Mat mask = new Mat();//不做掩码
  113. Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  114. Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  115. Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  116. for (int h = 0; h < oldHists[0].Rows; h++)
  117. {
  118. for (int j = oldHists.Length - 1; j >= 1; j--)
  119. {
  120. if (oldHists[j].At<float>(h) != oldHists[0].At<float>(h))
  121. {
  122. isGray = false;
  123. break;
  124. }
  125. }
  126. if (!isGray)
  127. break;
  128. }
  129. //if (this.AppWorkspace.ActiveDocumentWorkspace != null)
  130. //{
  131. // //获取gamma值
  132. // double gamma = this.AppWorkspace.ActiveDocumentWorkspace.HistogramGamma;
  133. // this.trackBar3.Value = Math.Min(299, (int)(gamma * 100));//备注:需要与AxioVision进行比较效果,调试一致
  134. // label7.Text = gamma.ToString("f2");
  135. // //获取对比度
  136. // double alpha = this.AppWorkspace.ActiveDocumentWorkspace.HistogramAlpha;
  137. // //获取亮度
  138. // double beta = this.AppWorkspace.ActiveDocumentWorkspace.HistogramBeta;
  139. // //计算对比度
  140. // label6.Text = alpha.ToString("f2");
  141. // trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  142. // //计算亮度
  143. // if (beta != double.Parse(label5.Text))
  144. // {
  145. // label5.Text = beta.ToString("f2");
  146. // trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  147. // }
  148. // this.numericUpDown1.Value = new decimal(new int[] {
  149. //(int)this.AppWorkspace.ActiveDocumentWorkspace.HistogramPercent,
  150. //0,
  151. //0,
  152. //0});
  153. // //numericUpDown1.Value = (decimal)this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramPercent;
  154. // skipButton.BtnSelect = this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled;
  155. // logButton.BtnSelect = this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled;
  156. //}
  157. updateHistImg(null);
  158. updateHistogramRect(true);
  159. }
  160. public void ResetCameraParamModel(CameraParamModel model)
  161. {
  162. m_cameraParamModel = model;
  163. InitColorAdjustRange();
  164. InitializeControlData();
  165. }
  166. int resolution_width = 2448;
  167. int resolution_height = 2048;
  168. private void InitColorAdjustRange()
  169. {
  170. //if (m_camera.IsOpen())
  171. //{
  172. // // 曝光时间
  173. // double aeMinVal = 0;
  174. // double aeMaxVal = 0;
  175. // double aeDftVal = 0;
  176. // m_camera.GetExposureTimeRange(ref aeMinVal, ref aeMaxVal, ref aeDftVal);
  177. // m_camera.m_drawAllHandler += new DrawAllHandler(CallbackDraw);
  178. // m_camera.StartWaitForFrame();
  179. // m_process = m_camera.StartDrawing(ref resolution_width, ref resolution_height);
  180. //}
  181. }
  182. ////#17904
  183. //private OpenCvSharp.Mat m_mat;
  184. ///// <summary>
  185. ///// 一个矩阵数组,用来接收直方图,记得全部初始化
  186. ///// </summary>
  187. //Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };
  188. ///// <summary>
  189. ///// 灰度图
  190. ///// </summary>
  191. //private bool isGray = true;
  192. ///// <summary>
  193. ///// BGR线条颜色
  194. ///// </summary>
  195. //private Scalar[] color = new Scalar[] { new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255), new Scalar(0, 0, 255, 255) };
  196. ///// <summary>
  197. ///// skip按钮
  198. ///// 显示直方图时,忽略黑色的灰度或颜色值。
  199. ///// 这使您可以为背景为黑色的图像实现有意义的直方图显示。
  200. ///// </summary>
  201. ///// <param name="sender"></param>
  202. ///// <param name="e"></param>
  203. //private void skipButton_Click(object sender, EventArgs e)
  204. //{
  205. // if (m_mat == null)
  206. // {
  207. // //MessageBox.Show("请打开图片");
  208. // return;
  209. // }
  210. // //设置按钮的选中/非选择的状态
  211. // skip000Button.BtnSelect = !skip000Button.BtnSelect;
  212. // //this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled = skipButton.BtnSelect;
  213. // updateHistImg(null);
  214. //}
  215. ///// <summary>
  216. ///// log按钮
  217. ///// 以对数比例显示直方图
  218. ///// </summary>
  219. ///// <param name="sender"></param>
  220. ///// <param name="e"></param>
  221. //private void logButton_Click(object sender, EventArgs e)
  222. //{
  223. // if (m_mat == null)
  224. // {
  225. // //MessageBox.Show("请打开图片");
  226. // return;
  227. // }
  228. // //设置按钮的选中/非选择的状态
  229. // log000Button.BtnSelect = !log000Button.BtnSelect;
  230. // //this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled = logButton.BtnSelect;
  231. // updateHistImg(null);
  232. //}
  233. ///// <summary>
  234. ///// 绘制
  235. ///// </summary>
  236. ///// <param name="pBuf"></param>
  237. ///// <param name="obj"></param>
  238. //public void CallbackDraw(byte[] pBuf, object obj, int channel)
  239. //{
  240. // lock (obj)
  241. // {
  242. // //m_isWaiting = false;
  243. // Console.WriteLine("接收全图buf");
  244. // m_camera.m_drawAllHandler -= new DrawAllHandler(CallbackDraw);
  245. // OpenCvSharp.Mat mat;
  246. // if (channel == 1)
  247. // {
  248. // mat = new OpenCvSharp.Mat(resolution_height, resolution_width/*m_resolution.Height, m_resolution.Width*/, OpenCvSharp.MatType.CV_8UC1, pBuf);
  249. // }
  250. // else
  251. // {
  252. // mat = new OpenCvSharp.Mat(resolution_height, resolution_width/*m_resolution.Height, m_resolution.Width*/, OpenCvSharp.MatType.CV_8UC3, pBuf);
  253. // }
  254. // OpenCvSharp.Cv2.Flip(mat, mat, 0);
  255. // if (m_mat != null)
  256. // {
  257. // m_mat.Dispose();
  258. // }
  259. // m_mat = mat.Clone();
  260. // //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
  261. // stopDrawing();
  262. // if (mat != null)
  263. // {
  264. // mat.Dispose();
  265. // }
  266. // this.showHistImg(m_mat);
  267. // }
  268. //}
  269. //private void showHistImg(Mat BoxMat)
  270. //{
  271. // Mat[] mats = Cv2.Split(BoxMat);//一张图片,将panda拆分成3个图片装进mat
  272. // if (mats.Count() == 1)
  273. // {
  274. // isGray = true;
  275. // }
  276. // else
  277. // {
  278. // isGray = false;
  279. // }
  280. // if (isGray)
  281. // {
  282. // Mat[] mats011 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  283. // int[] channels011 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  284. // int[] histsize11 = new int[] { 256 };//一个通道,初始化为256箱子
  285. // Rangef[] range11 = new Rangef[1];//一个通道,范围
  286. // range11[0].Start = 0.0F;//从0开始(含)
  287. // range11[0].End = 256.0F;//到256结束(不含)
  288. // Mat mask11 = new Mat();//不做掩码
  289. // Cv2.CalcHist(mats011, channels011, mask11, oldHists[0], 1, histsize11, range11);//对被拆分的图片单独进行计算
  290. // updateHistImgGray(oldHists);
  291. // return;
  292. // }
  293. // Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  294. // Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  295. // Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  296. // int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  297. // int[] channels1 = new int[] { 0 };
  298. // int[] channels2 = new int[] { 0 };
  299. // int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  300. // Rangef[] range = new Rangef[1];//一个通道,范围
  301. // range[0].Start = 0.0F;//从0开始(含)
  302. // range[0].End = 256.0F;//到256结束(不含)
  303. // Mat mask = new Mat();//不做掩码
  304. // Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  305. // Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  306. // Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  307. // for (int h = 0; h < oldHists[0].Rows; h++)
  308. // {
  309. // for (int j = oldHists.Length - 1; j >= 1; j--)
  310. // {
  311. // if (oldHists[j].At<float>(h) != oldHists[0].At<float>(h))
  312. // {
  313. // isGray = false;
  314. // break;
  315. // }
  316. // }
  317. // if (!isGray)
  318. // break;
  319. // }
  320. // updateHistImg(oldHists);
  321. //}
  322. ///// <summary>
  323. ///// 绘制直方图-单通道
  324. ///// </summary>
  325. ///// <param name="hist"></param>
  326. ///// <returns></returns>
  327. //private unsafe void updateHistImgGray(Mat[] hists)
  328. //{
  329. // if (m_mat == null)
  330. // {
  331. // return;
  332. // }
  333. // Mat[] mats = Cv2.Split(m_mat);//一张图片,将panda拆分成3个图片装进mat
  334. // //if (mats.Count() == 1)
  335. // //{
  336. // // isGray = true;
  337. // //}
  338. // //else
  339. // //{
  340. // // isGray = false;
  341. // //}
  342. // Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  343. // //Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  344. // //Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  345. // if (hists == null)
  346. // {
  347. // hists = new Mat[] { new Mat()/*, new Mat(), new Mat()*/ };//一个矩阵数组,用来接收直方图,记得全部初始化
  348. // int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  349. // //int[] channels1 = new int[] { 0 };
  350. // //int[] channels2 = new int[] { 0 };
  351. // int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  352. // Rangef[] range = new Rangef[1];//一个通道,范围
  353. // range[0].Start = 0.0F;//从0开始(含)
  354. // range[0].End = 256.0F;//到256结束(不含)
  355. // Mat mask = new Mat();//不做掩码
  356. // Cv2.CalcHist(mats0, channels0, mask, hists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  357. // //Cv2.CalcHist(mats1, channels1, mask, hists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  358. // //Cv2.CalcHist(mats2, channels2, mask, hists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  359. // if (log000Button.BtnSelect)
  360. // {
  361. // //取对数
  362. // for (int j = 0; j < hists.Length; j++)
  363. // {
  364. // List<float> ProbPixel = new List<float>();
  365. // for (int i = 0; i < hists[j].Rows; i++)
  366. // {
  367. // if (((float*)hists[j].Ptr(0))[i] == 0)
  368. // {
  369. // ((float*)hists[j].Ptr(0))[i] = ((float*)hists[j].Ptr(0))[i];
  370. // ProbPixel.Add(0);
  371. // }
  372. // else
  373. // {
  374. // ((float*)hists[j].Ptr(0))[i] = (float)Math.Log10(((float*)hists[j].Ptr(0))[i]/* + 9*/);
  375. // ProbPixel.Add(1);
  376. // }
  377. // }
  378. // double max1jVal = 0;
  379. // double min1jVal = 0;
  380. // //找到直方图中的最大值和最小值
  381. // Cv2.MinMaxLoc(hists[j], out min1jVal, out max1jVal);
  382. // if (min1jVal >= max1jVal)
  383. // {
  384. // continue;
  385. // }
  386. // //归一化到0~255,并根据AxioVision添加偏置值
  387. // for (int i = 0; i < hists[j].Rows; i++)
  388. // {
  389. // ((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);
  390. // }
  391. // }
  392. // }
  393. // if (skip000Button.BtnSelect)
  394. // {
  395. // //去掉黑色部分 和 白色部分
  396. // for (int j = 0; j < hists.Length; j++)
  397. // {
  398. // ((float*)hists[j].Ptr(0))[0] = 0;
  399. // ((float*)hists[j].Ptr(0))[255] = 0;
  400. // }
  401. // }
  402. // }
  403. // //double max2Val = 0;
  404. // //double max1Val = 0;
  405. // double max0Val = 0;
  406. // double minVal = 0;
  407. // //为了更好显示直方图细节,使用4倍尺寸绘制直方图
  408. // int histSize = hists[0].Rows * 4;
  409. // Mat histImg = new Mat(histSize, histSize, MatType.CV_8UC3, new Scalar(255, 255, 255));
  410. // //找到直方图中的最大值和最小值
  411. // //Cv2.MinMaxLoc(hists[2], out minVal, out max2Val);
  412. // //Cv2.MinMaxLoc(hists[1], out minVal, out max1Val);
  413. // Cv2.MinMaxLoc(hists[0], out minVal, out max0Val);
  414. // double maxVal = max0Val;// Math.Max(max2Val, Math.Max(max0Val, max1Val));
  415. // if (maxVal < 1)
  416. // return;
  417. // // 设置最大峰值为图像高度的90%
  418. // double hpt = 0.9 * histSize;
  419. // //灰度图的显示直方图较为简单,显示一个通道即可
  420. // if (isGray)
  421. // {
  422. // Mat hist = hists[0];
  423. // int lastY2 = histSize - 1;
  424. // for (int h = 0; h < hists[0].Rows; h++)
  425. // {
  426. // int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  427. // int lastY1 = lastY2;
  428. // lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  429. // if (lastY2 < lastY1)
  430. // {
  431. // 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);
  432. // }
  433. // else
  434. // {
  435. // 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);
  436. // }
  437. // }
  438. // }
  439. // //彩度图显示BGR三个通道的直方图
  440. // else
  441. // {
  442. // int lineWidth = 2;
  443. // for (int j = hists.Length - 1; j >= 0; j--)
  444. // {
  445. // Mat hist = hists[j];
  446. // int lastY2 = histSize - 1;
  447. // for (int h = 0; h < hists[0].Rows; h++)
  448. // {
  449. // int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  450. // int lastY1 = lastY2;
  451. // lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  452. // if (h > 0)
  453. // {
  454. // //显示0.5位置的直方图,这样与AxioVision效果更加近似
  455. // int lasty12 = (lastY1 + lastY2) / 2;
  456. // if (lasty12 < lastY1)
  457. // {
  458. // 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);
  459. // }
  460. // else
  461. // {
  462. // 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*/);
  463. // }
  464. // if (lastY2 < lasty12)
  465. // {
  466. // Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lasty12 - 2)), color[j], lineWidth, LineTypes.Link4);
  467. // }
  468. // else
  469. // {
  470. // 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*/);
  471. // }
  472. // }
  473. // else
  474. // {
  475. // //灰度值为0的线的绘制
  476. // if (lastY2 < lastY1)
  477. // {
  478. // Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
  479. // }
  480. // else
  481. // {
  482. // 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*/);
  483. // }
  484. // }
  485. // }
  486. // }
  487. // }
  488. // this.picture000Box1.BackgroundImage/*Image*/ = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  489. //}
  490. ///// <summary>
  491. ///// 绘制直方图
  492. ///// </summary>
  493. ///// <param name="hist"></param>
  494. ///// <returns></returns>
  495. //private unsafe void updateHistImg(Mat[] hists)
  496. //{
  497. // if (m_mat == null)
  498. // {
  499. // return;
  500. // }
  501. // Mat[] mats = Cv2.Split(m_mat);//一张图片,将panda拆分成3个图片装进mat
  502. // if (mats.Count() == 1)
  503. // {
  504. // isGray = true;
  505. // }
  506. // else
  507. // {
  508. // isGray = false;
  509. // }
  510. // if (isGray)
  511. // {
  512. // updateHistImgGray(hists);
  513. // return;
  514. // }
  515. // Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  516. // Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  517. // Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  518. // if (hists == null)
  519. // {
  520. // hists = new Mat[] { new Mat(), new Mat(), new Mat() };//一个矩阵数组,用来接收直方图,记得全部初始化
  521. // int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  522. // int[] channels1 = new int[] { 0 };
  523. // int[] channels2 = new int[] { 0 };
  524. // int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  525. // Rangef[] range = new Rangef[1];//一个通道,范围
  526. // range[0].Start = 0.0F;//从0开始(含)
  527. // range[0].End = 256.0F;//到256结束(不含)
  528. // Mat mask = new Mat();//不做掩码
  529. // Cv2.CalcHist(mats0, channels0, mask, hists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  530. // Cv2.CalcHist(mats1, channels1, mask, hists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  531. // Cv2.CalcHist(mats2, channels2, mask, hists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  532. // if (log000Button.BtnSelect)
  533. // {
  534. // //取对数
  535. // for (int j = 0; j < hists.Length; j++)
  536. // {
  537. // List<float> ProbPixel = new List<float>();
  538. // for (int i = 0; i < hists[j].Rows; i++)
  539. // {
  540. // if (((float*)hists[j].Ptr(0))[i] == 0)
  541. // {
  542. // ((float*)hists[j].Ptr(0))[i] = ((float*)hists[j].Ptr(0))[i];
  543. // ProbPixel.Add(0);
  544. // }
  545. // else
  546. // {
  547. // ((float*)hists[j].Ptr(0))[i] = (float)Math.Log10(((float*)hists[j].Ptr(0))[i]/* + 9*/);
  548. // ProbPixel.Add(1);
  549. // }
  550. // }
  551. // double max1jVal = 0;
  552. // double min1jVal = 0;
  553. // //找到直方图中的最大值和最小值
  554. // Cv2.MinMaxLoc(hists[j], out min1jVal, out max1jVal);
  555. // if (min1jVal >= max1jVal)
  556. // {
  557. // continue;
  558. // }
  559. // //归一化到0~255,并根据AxioVision添加偏置值
  560. // for (int i = 0; i < hists[j].Rows; i++)
  561. // {
  562. // ((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);
  563. // }
  564. // }
  565. // }
  566. // if (skip000Button.BtnSelect)
  567. // {
  568. // //去掉黑色部分 和 白色部分
  569. // for (int j = 0; j < hists.Length; j++)
  570. // {
  571. // ((float*)hists[j].Ptr(0))[0] = 0;
  572. // ((float*)hists[j].Ptr(0))[255] = 0;
  573. // }
  574. // }
  575. // }
  576. // double max2Val = 0;
  577. // double max1Val = 0;
  578. // double max0Val = 0;
  579. // double minVal = 0;
  580. // //为了更好显示直方图细节,使用4倍尺寸绘制直方图
  581. // int histSize = hists[0].Rows * 4;
  582. // Mat histImg = new Mat(histSize, histSize, MatType.CV_8UC3, new Scalar(255, 255, 255));
  583. // //找到直方图中的最大值和最小值
  584. // Cv2.MinMaxLoc(hists[2], out minVal, out max2Val);
  585. // Cv2.MinMaxLoc(hists[1], out minVal, out max1Val);
  586. // Cv2.MinMaxLoc(hists[0], out minVal, out max0Val);
  587. // double maxVal = Math.Max(max2Val, Math.Max(max0Val, max1Val));
  588. // if (maxVal < 1)
  589. // return;
  590. // // 设置最大峰值为图像高度的90%
  591. // double hpt = 0.9 * histSize;
  592. // //灰度图的显示直方图较为简单,显示一个通道即可
  593. // if (isGray)
  594. // {
  595. // Mat hist = hists[0];
  596. // int lastY2 = histSize - 1;
  597. // for (int h = 0; h < hists[0].Rows; h++)
  598. // {
  599. // int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  600. // int lastY1 = lastY2;
  601. // lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  602. // if (lastY2 < lastY1)
  603. // {
  604. // 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);
  605. // }
  606. // else
  607. // {
  608. // 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);
  609. // }
  610. // }
  611. // }
  612. // //彩度图显示BGR三个通道的直方图
  613. // else
  614. // {
  615. // int lineWidth = 2;
  616. // for (int j = hists.Length - 1; j >= 0; j--)
  617. // {
  618. // Mat hist = hists[j];
  619. // int lastY2 = histSize - 1;
  620. // for (int h = 0; h < hists[0].Rows; h++)
  621. // {
  622. // int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  623. // int lastY1 = lastY2;
  624. // lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  625. // if (h > 0)
  626. // {
  627. // //显示0.5位置的直方图,这样与AxioVision效果更加近似
  628. // int lasty12 = (lastY1 + lastY2) / 2;
  629. // if (lasty12 < lastY1)
  630. // {
  631. // 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);
  632. // }
  633. // else
  634. // {
  635. // 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*/);
  636. // }
  637. // if (lastY2 < lasty12)
  638. // {
  639. // Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lasty12 - 2)), color[j], lineWidth, LineTypes.Link4);
  640. // }
  641. // else
  642. // {
  643. // 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*/);
  644. // }
  645. // }
  646. // else
  647. // {
  648. // //灰度值为0的线的绘制
  649. // if (lastY2 < lastY1)
  650. // {
  651. // Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
  652. // }
  653. // else
  654. // {
  655. // 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*/);
  656. // }
  657. // }
  658. // }
  659. // }
  660. // }
  661. // this.picture000Box1.BackgroundImage/*Image*/ = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  662. //}
  663. //private void stopDrawing()
  664. //{
  665. // //创建一个委托,用于封装一个方法,在这里是封装了 控制更新控件 的方法
  666. // Action invokeAction = new Action(stopDrawing);
  667. // //判断操作控件的线程是否创建控件的线程
  668. // //调用方调用方位于创建控件所在的线程以外的线程中,如果在其他线程则对控件进行方法调用时必须调用 Invoke 方法
  669. // if (this.InvokeRequired)
  670. // {
  671. // //与调用线程不同的线程上创建(说明您必须通过 Invoke 方法对控件进行调用)
  672. // this.Invoke(invokeAction);
  673. // }
  674. // else
  675. // {
  676. // m_camera.StopDrawing(m_process);
  677. // m_camera.StopWaitForFrame();
  678. // ////窗体线程,即主线程
  679. // //shuaxinButton.Enabled = true;
  680. // }
  681. //}
  682. private string UpdateExposureTime(UInt64 exposureTime)
  683. {
  684. string str = "";
  685. int sec = 0;
  686. int msec = 0;
  687. int usec = 0;
  688. m_camera.UpdateExposureTime(ref sec, ref msec, ref usec, exposureTime);
  689. if (sec > 0)
  690. {
  691. str += sec + "s";
  692. }
  693. else if (msec > 0)
  694. {
  695. str += msec + "ms";
  696. }
  697. else if (usec > 0)
  698. {
  699. str += usec + "μs";
  700. }
  701. return str;
  702. }
  703. private void UpdateExposureUI(int autoExposure)
  704. {
  705. if (autoExposure == 1)
  706. {
  707. // 设置到相机
  708. if (m_immediately)
  709. {
  710. // 自动曝光
  711. m_camera.SetExposureMode(ExposureMode.AUTO);
  712. m_aeTimer.Start();
  713. }
  714. }
  715. else
  716. {
  717. // 设置到相机
  718. if (m_immediately)
  719. {
  720. m_camera.SetExposureMode(ExposureMode.MANUAL);
  721. m_aeTimer.Stop();
  722. }
  723. }
  724. }
  725. /// <summary>
  726. /// 设置下拉等数据源
  727. /// </summary>
  728. private void InitializeControlData()
  729. {
  730. m_aeTimer = new System.Timers.Timer(1000);
  731. m_aeTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerAutoExposure);
  732. m_aeTimer.AutoReset = true;
  733. m_aeTimer.SynchronizingObject = this;
  734. UpdateExposureUI(m_cameraParamModel.parame.ATExposure);
  735. // 增益值调整
  736. int gainValue = m_cameraParamModel.parame.GlobalGain;
  737. //// 白平衡
  738. //if (m_cameraParamModel.parame.WhiteBalance == 1)
  739. //{
  740. // AutoWhiteBalance(true);
  741. //}
  742. //else
  743. //{
  744. // if (m_cameraParamModel.parame.FMExposure == 1)
  745. // {
  746. // m_camera.SetColorTemperatureByString("3200K");
  747. // }
  748. // else if (m_cameraParamModel.parame.FMExposure == 2)
  749. // {
  750. // m_camera.SetColorTemperatureByString("5500K");
  751. // }
  752. // AutoWhiteBalance(false);
  753. //}
  754. }
  755. private void InitializeLanguageText()
  756. {
  757. this.label0005.Text = PdnResources.GetString("Menu.timeofexposure.text")+":";
  758. this.label3.Text = PdnResources.GetString("Menu.Gammavalue.text")+":";
  759. this.label2.Text = PdnResources.GetString("Menu.Contrast.text")+":";
  760. this.label1.Text = PdnResources.GetString("Menu.luminance.text")+":";
  761. this.button5.Text = PdnResources.GetString("Menu.Originalstate.text");
  762. this.button4.Text = PdnResources.GetString("Menu.Gammavalue.text")+"0.45";
  763. this.button2.Text = PdnResources.GetString("Menu.optimal.text");
  764. }
  765. private void InitializeComponent()
  766. {
  767. this.label0005 = new System.Windows.Forms.Label();
  768. this.label7 = new System.Windows.Forms.Label();
  769. this.trackBar3 = new PaintDotNet.CustomControl.TriangleTrackBar();
  770. this.label6 = new System.Windows.Forms.Label();
  771. this.trackBar2 = new PaintDotNet.CustomControl.TriangleTrackBar();
  772. this.label5 = new System.Windows.Forms.Label();
  773. this.trackBar1 = new PaintDotNet.CustomControl.TriangleTrackBar();
  774. this.label4 = new System.Windows.Forms.Label();
  775. this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
  776. this.label3 = new System.Windows.Forms.Label();
  777. this.label2 = new System.Windows.Forms.Label();
  778. this.label1 = new System.Windows.Forms.Label();
  779. this.button5 = new System.Windows.Forms.Button();
  780. this.button4 = new System.Windows.Forms.Button();
  781. this.button3 = new System.Windows.Forms.Button();
  782. this.button2 = new System.Windows.Forms.Button();
  783. this.ucTrackBar1 = new PaintDotNet.CustomControl.UCTrackBar();
  784. this.logButton = new PaintDotNet.CustomControl.SelectButton();
  785. this.skipButton = new PaintDotNet.CustomControl.SelectButton();
  786. this.pictureBox1 = new System.Windows.Forms.PictureBox();
  787. ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
  788. ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
  789. this.SuspendLayout();
  790. //
  791. // label0005
  792. //
  793. this.label0005.AutoSize = true;
  794. this.label0005.Location = new System.Drawing.Point(24, 39);
  795. this.label0005.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
  796. this.label0005.Name = "label0005";
  797. this.label0005.Size = new System.Drawing.Size(82, 15);
  798. this.label0005.TabIndex = 12;
  799. this.label0005.Text = "曝光时间:";
  800. //
  801. // label7
  802. //
  803. this.label7.AutoSize = true;
  804. this.label7.Location = new System.Drawing.Point(332, 237);
  805. this.label7.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  806. this.label7.Name = "label7";
  807. this.label7.Size = new System.Drawing.Size(29, 12);
  808. this.label7.TabIndex = 59;
  809. this.label7.Text = "1.00";
  810. this.label7.TextChanged += new System.EventHandler(this.label7_Changed);
  811. //
  812. // trackBar3
  813. //
  814. this.trackBar3.Location = new System.Drawing.Point(127, 229);
  815. this.trackBar3.Maximum = 299;
  816. this.trackBar3.Minimum = 0;
  817. this.trackBar3.Name = "trackBar3";
  818. this.trackBar3.Size = new System.Drawing.Size(200, 30);
  819. this.trackBar3.TabIndex = 58;
  820. this.trackBar3.Value = 100;
  821. this.trackBar3.TrackBarScroll += new System.EventHandler(this.trackBar3_Scroll);
  822. //
  823. // label6
  824. //
  825. this.label6.AutoSize = true;
  826. this.label6.Location = new System.Drawing.Point(332, 201);
  827. this.label6.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  828. this.label6.Name = "label6";
  829. this.label6.Size = new System.Drawing.Size(29, 12);
  830. this.label6.TabIndex = 57;
  831. this.label6.Text = "1.00";
  832. this.label6.TextChanged += new System.EventHandler(this.label6_Changed);
  833. //
  834. // trackBar2
  835. //
  836. this.trackBar2.Location = new System.Drawing.Point(127, 194);
  837. this.trackBar2.Maximum = 999;
  838. this.trackBar2.Minimum = 0;
  839. this.trackBar2.Name = "trackBar2";
  840. this.trackBar2.Size = new System.Drawing.Size(200, 30);
  841. this.trackBar2.TabIndex = 56;
  842. this.trackBar2.Value = 100;
  843. this.trackBar2.TrackBarScroll += new System.EventHandler(this.trackBar2_Scroll);
  844. //
  845. // label5
  846. //
  847. this.label5.AutoSize = true;
  848. this.label5.Location = new System.Drawing.Point(332, 165);
  849. this.label5.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  850. this.label5.Name = "label5";
  851. this.label5.Size = new System.Drawing.Size(29, 12);
  852. this.label5.TabIndex = 55;
  853. this.label5.Text = "-0.5";
  854. this.label5.TextChanged += new System.EventHandler(this.label5_Changed);
  855. //
  856. // trackBar1
  857. //
  858. this.trackBar1.Location = new System.Drawing.Point(127, 158);
  859. this.trackBar1.Maximum = 200;
  860. this.trackBar1.Minimum = -200;
  861. this.trackBar1.Name = "trackBar1";
  862. this.trackBar1.Size = new System.Drawing.Size(200, 30);
  863. this.trackBar1.TabIndex = 54;
  864. this.trackBar1.Value = -50;
  865. this.trackBar1.TrackBarScroll += new System.EventHandler(this.trackBar1_Scroll);
  866. //
  867. // label4
  868. //
  869. this.label4.AutoSize = true;
  870. this.label4.Location = new System.Drawing.Point(356, 279);
  871. this.label4.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  872. this.label4.Name = "label4";
  873. this.label4.Size = new System.Drawing.Size(17, 12);
  874. this.label4.TabIndex = 53;
  875. this.label4.Text = "‰";
  876. //
  877. // numericUpDown1
  878. //
  879. this.numericUpDown1.Location = new System.Drawing.Point(302, 275);
  880. this.numericUpDown1.Margin = new System.Windows.Forms.Padding(2);
  881. this.numericUpDown1.Maximum = new decimal(new int[] {
  882. 499,
  883. 0,
  884. 0,
  885. 0});
  886. this.numericUpDown1.Name = "numericUpDown1";
  887. this.numericUpDown1.Size = new System.Drawing.Size(50, 21);
  888. this.numericUpDown1.TabIndex = 52;
  889. this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
  890. this.numericUpDown1.Value = new decimal(new int[] {
  891. 200,
  892. 0,
  893. 0,
  894. 0});
  895. //
  896. // label3
  897. //
  898. this.label3.AutoSize = true;
  899. this.label3.Location = new System.Drawing.Point(73, 237);
  900. this.label3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  901. this.label3.Name = "label3";
  902. this.label3.Size = new System.Drawing.Size(53, 12);
  903. this.label3.TabIndex = 51;
  904. this.label3.Text = "伽马值:";
  905. //
  906. // label2
  907. //
  908. this.label2.AutoSize = true;
  909. this.label2.Location = new System.Drawing.Point(73, 201);
  910. this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  911. this.label2.Name = "label2";
  912. this.label2.Size = new System.Drawing.Size(53, 12);
  913. this.label2.TabIndex = 50;
  914. this.label2.Text = "对比度:";
  915. //
  916. // label1
  917. //
  918. this.label1.AutoSize = true;
  919. this.label1.Location = new System.Drawing.Point(85, 165);
  920. this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
  921. this.label1.Name = "label1";
  922. this.label1.Size = new System.Drawing.Size(41, 12);
  923. this.label1.TabIndex = 49;
  924. this.label1.Text = "亮度:";
  925. //
  926. // button5
  927. //
  928. this.button5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
  929. this.button5.Location = new System.Drawing.Point(184, 305);
  930. this.button5.Name = "button5";
  931. this.button5.Size = new System.Drawing.Size(75, 23);
  932. this.button5.TabIndex = 48;
  933. this.button5.Text = "原始状态";
  934. this.button5.UseVisualStyleBackColor = true;
  935. this.button5.Click += new System.EventHandler(this.button5_Click);
  936. //
  937. // button4
  938. //
  939. this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
  940. this.button4.Location = new System.Drawing.Point(70, 305);
  941. this.button4.Name = "button4";
  942. this.button4.Size = new System.Drawing.Size(75, 23);
  943. this.button4.TabIndex = 47;
  944. this.button4.Text = "伽马值0.45";
  945. this.button4.UseVisualStyleBackColor = true;
  946. this.button4.Click += new System.EventHandler(this.button4_Click);
  947. //
  948. // button3
  949. //
  950. this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
  951. this.button3.Location = new System.Drawing.Point(299, 305);
  952. this.button3.Name = "button3";
  953. this.button3.Size = new System.Drawing.Size(75, 23);
  954. this.button3.TabIndex = 46;
  955. this.button3.Text = "MIN/MAX";
  956. this.button3.UseVisualStyleBackColor = true;
  957. this.button3.Click += new System.EventHandler(this.button3_Click);
  958. //
  959. // button2
  960. //
  961. this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
  962. this.button2.Location = new System.Drawing.Point(184, 272);
  963. this.button2.Name = "button2";
  964. this.button2.Size = new System.Drawing.Size(75, 23);
  965. this.button2.TabIndex = 45;
  966. this.button2.Text = "最佳";
  967. this.button2.UseVisualStyleBackColor = true;
  968. this.button2.Click += new System.EventHandler(this.button2_Click);
  969. //
  970. // ucTrackBar1
  971. //
  972. this.ucTrackBar1.DcimalDigits = 0;
  973. this.ucTrackBar1.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(77)))), ((int)(((byte)(59)))));
  974. this.ucTrackBar1.LineWidth = 8F;
  975. this.ucTrackBar1.Location = new System.Drawing.Point(68, 134);
  976. this.ucTrackBar1.MaxValue = 255F;
  977. this.ucTrackBar1.MinValue = 0F;
  978. this.ucTrackBar1.Name = "ucTrackBar1";
  979. this.ucTrackBar1.Size = new System.Drawing.Size(274, 20);
  980. this.ucTrackBar1.TabIndex = 44;
  981. this.ucTrackBar1.Text = "ucTrackBar1";
  982. this.ucTrackBar1.Value1 = 0F;
  983. this.ucTrackBar1.Value2 = 127F;
  984. this.ucTrackBar1.Value3 = 255F;
  985. this.ucTrackBar1.Value1Changed += new System.EventHandler(this.ucTrackBar1_Value1Changed);
  986. this.ucTrackBar1.Value2Changed += new System.EventHandler(this.ucTrackBar1_Value2Changed);
  987. this.ucTrackBar1.Value3Changed += new System.EventHandler(this.ucTrackBar1_Value3Changed);
  988. //
  989. // logButton
  990. //
  991. this.logButton.BackColor = System.Drawing.SystemColors.ControlDark;
  992. this.logButton.BtnSelect = false;
  993. this.logButton.BtnText = "log";
  994. this.logButton.Location = new System.Drawing.Point(339, 43);
  995. this.logButton.Name = "logButton";
  996. this.logButton.Size = new System.Drawing.Size(41, 21);
  997. this.logButton.TabIndex = 43;
  998. this.logButton.Click += new System.EventHandler(this.logButton_Click);
  999. //
  1000. // skipButton
  1001. //
  1002. this.skipButton.BackColor = System.Drawing.SystemColors.ControlDark;
  1003. this.skipButton.BtnSelect = false;
  1004. this.skipButton.BtnText = "skip";
  1005. this.skipButton.Location = new System.Drawing.Point(339, 74);
  1006. this.skipButton.Name = "skipButton";
  1007. this.skipButton.Size = new System.Drawing.Size(41, 21);
  1008. this.skipButton.TabIndex = 42;
  1009. this.skipButton.Click += new System.EventHandler(this.skipButton_Click);
  1010. //
  1011. // pictureBox1
  1012. //
  1013. this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
  1014. | System.Windows.Forms.AnchorStyles.Left)
  1015. | System.Windows.Forms.AnchorStyles.Right)));
  1016. this.pictureBox1.BackColor = System.Drawing.Color.White;
  1017. this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
  1018. this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
  1019. this.pictureBox1.Location = new System.Drawing.Point(76, 9);
  1020. this.pictureBox1.Name = "pictureBox1";
  1021. this.pictureBox1.Size = new System.Drawing.Size(256, 124);
  1022. this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
  1023. this.pictureBox1.TabIndex = 41;
  1024. this.pictureBox1.TabStop = false;
  1025. //
  1026. // DisplayCameraControl
  1027. //
  1028. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
  1029. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  1030. this.Controls.Add(this.label7);
  1031. this.Controls.Add(this.trackBar3);
  1032. this.Controls.Add(this.label6);
  1033. this.Controls.Add(this.trackBar2);
  1034. this.Controls.Add(this.label5);
  1035. this.Controls.Add(this.trackBar1);
  1036. this.Controls.Add(this.label4);
  1037. this.Controls.Add(this.numericUpDown1);
  1038. this.Controls.Add(this.label3);
  1039. this.Controls.Add(this.label2);
  1040. this.Controls.Add(this.label1);
  1041. this.Controls.Add(this.button5);
  1042. this.Controls.Add(this.button4);
  1043. this.Controls.Add(this.button3);
  1044. this.Controls.Add(this.button2);
  1045. this.Controls.Add(this.ucTrackBar1);
  1046. this.Controls.Add(this.logButton);
  1047. this.Controls.Add(this.skipButton);
  1048. this.Controls.Add(this.pictureBox1);
  1049. this.Name = "DisplayCameraControl";
  1050. this.Size = new System.Drawing.Size(490, 345);
  1051. ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
  1052. ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
  1053. this.ResumeLayout(false);
  1054. this.PerformLayout();
  1055. }
  1056. public void OnTimerAutoExposure(object source, System.Timers.ElapsedEventArgs e)
  1057. {
  1058. double paramValue = m_camera.GetExposureTime();
  1059. decimal txtVale = 0;
  1060. int sec = 0;
  1061. int msec = 0;
  1062. int usec = 0;
  1063. m_camera.UpdateExposureTime(ref sec, ref msec, ref usec, (UInt64)(paramValue * 1000));
  1064. //UpdateExposureTime((UInt64)paramValue * 1000);
  1065. }
  1066. /// <summary>
  1067. /// 最佳
  1068. /// </summary>
  1069. public void BestButtonMethod()
  1070. {
  1071. OpenCvSharp.Point startIndex = this.getStartIndex(this.OldMat, oldHists, (float)numericUpDown1.Value);
  1072. //计算对比度
  1073. label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
  1074. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  1075. //计算亮度
  1076. label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
  1077. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  1078. this.scrollMethod();
  1079. updateHistogramRect(true);
  1080. }
  1081. /// <summary>
  1082. /// 最大最小
  1083. /// </summary>
  1084. public void MaxMinButtonMethod()
  1085. {
  1086. OpenCvSharp.Point startIndex = this.getStartIndex(this.OldMat, oldHists, 0);
  1087. //计算对比度
  1088. label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
  1089. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  1090. //计算亮度
  1091. label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
  1092. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  1093. //this.parentf
  1094. //this.scrollMethod();
  1095. updateHistogramRect(true);
  1096. }
  1097. /// <summary>
  1098. /// 原始状态
  1099. /// </summary>
  1100. public void OriginButtonMethod()
  1101. {
  1102. this.trackBar1.Value = -50;
  1103. this.trackBar2.Value = 100;
  1104. this.trackBar3.Value = 100;
  1105. label5.Text = (trackBar1.Value / 100.0).ToString("f2");
  1106. label6.Text = (trackBar2.Value / 100.0).ToString("f2");
  1107. label7.Text = (trackBar3.Value / 100.0).ToString("f2");
  1108. if (this.OldMat == null)
  1109. {
  1110. //MessageBox.Show("请打开图片");
  1111. return;
  1112. }
  1113. updateHistogramRect(true);
  1114. /**待处理**///this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.ResetBoxBitmap();
  1115. //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(oldMat));
  1116. }
  1117. /// <summary>
  1118. /// 伽马0.45
  1119. /// </summary>
  1120. public void Gamma45ButtonMethod()
  1121. {
  1122. this.trackBar3.Value = 45;
  1123. label7.Text = (trackBar3.Value / 100.0).ToString("f2");
  1124. this.scrollMethod();
  1125. updateHistogramRect(true);
  1126. }
  1127. /// <summary>
  1128. /// 最佳
  1129. /// 确定当前直方图中排除图像中包含的像素的1‰的值,
  1130. /// 并在屏幕上显示以此方式确定的灰度或颜色范围。
  1131. /// (您可以将1‰的值调整为适合您的需求。)
  1132. /// https://blog.csdn.net/qq_20095389/article/details/83658878
  1133. /// https://blog.csdn.net/lantishua/article/details/46377325
  1134. /// </summary>
  1135. /// <param name="sender"></param>
  1136. /// <param name="e"></param>
  1137. private void button2_Click(object sender, EventArgs e)
  1138. {
  1139. if (this.OldMat == null)
  1140. {
  1141. return;
  1142. }
  1143. this.BestButtonMethod();
  1144. }
  1145. /// <summary>
  1146. /// 最大最小
  1147. /// </summary>
  1148. /// <param name="sender"></param>
  1149. /// <param name="e"></param>
  1150. private void button3_Click(object sender, EventArgs e)
  1151. {
  1152. if (this.OldMat == null)
  1153. {
  1154. return;
  1155. }
  1156. this.MaxMinButtonMethod();
  1157. }
  1158. /// <summary>
  1159. /// 伽马0.45
  1160. /// 需要调整直线的弧度
  1161. /// 直方图曲线根据伽马值进行变化
  1162. /// </summary>
  1163. /// <param name="sender"></param>
  1164. /// <param name="e"></param>
  1165. private void button4_Click(object sender, EventArgs e)
  1166. {
  1167. if (this.OldMat == null)
  1168. {
  1169. return;
  1170. }
  1171. this.Gamma45ButtonMethod();
  1172. }
  1173. /// <summary>
  1174. /// 原始状态
  1175. /// </summary>
  1176. /// <param name="sender"></param>
  1177. /// <param name="e"></param>
  1178. private void button5_Click(object sender, EventArgs e)
  1179. {
  1180. this.OriginButtonMethod();
  1181. }
  1182. /// <summary>
  1183. /// skip按钮
  1184. /// 显示直方图时,忽略黑色的灰度或颜色值。
  1185. /// 这使您可以为背景为黑色的图像实现有意义的直方图显示。
  1186. /// </summary>
  1187. /// <param name="sender"></param>
  1188. /// <param name="e"></param>
  1189. private void skipButton_Click(object sender, EventArgs e)
  1190. {
  1191. if (this.OldMat == null)
  1192. {
  1193. return;
  1194. }
  1195. //设置按钮的选中/非选择的状态
  1196. skipButton.BtnSelect = !skipButton.BtnSelect;
  1197. //this.AppWorkspace.ActiveDocumentWorkspace.HistogramSkipEnabled = skipButton.BtnSelect;
  1198. updateHistImg(null);
  1199. }
  1200. /// <summary>
  1201. /// log按钮
  1202. /// 以对数比例显示直方图
  1203. /// </summary>
  1204. /// <param name="sender"></param>
  1205. /// <param name="e"></param>
  1206. private void logButton_Click(object sender, EventArgs e)
  1207. {
  1208. if (this.OldMat == null)
  1209. {
  1210. return;
  1211. }
  1212. //设置按钮的选中/非选择的状态
  1213. logButton.BtnSelect = !logButton.BtnSelect;
  1214. //this.AppWorkspace.ActiveDocumentWorkspace.HistogramLogEnabled = logButton.BtnSelect;
  1215. updateHistImg(null);
  1216. }
  1217. /// <summary>
  1218. /// 最佳设置的数值改变
  1219. /// </summary>
  1220. /// <param name="sender"></param>
  1221. /// <param name="e"></param>
  1222. private void numericUpDown1_ValueChanged(object sender, EventArgs e)
  1223. {
  1224. //this.AppWorkspace.ActiveDocumentWorkspace.HistogramPercent = (int)numericUpDown1.Value;
  1225. }
  1226. /// <summary>
  1227. /// 亮度改变
  1228. /// </summary>
  1229. /// <param name="sender"></param>
  1230. /// <param name="e"></param>
  1231. private void trackBar1_Scroll(object sender, EventArgs e)
  1232. {
  1233. trackBar1Value = trackBar1.Value;
  1234. //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.HistogramBeta = trackBar1.Value / 100.0;
  1235. label5.Text = (trackBar1.Value / 100.0).ToString("f2");
  1236. updateHistogramRect(true);
  1237. }
  1238. /// <summary>
  1239. /// 亮度改变
  1240. /// </summary>
  1241. /// <param name="sender"></param>
  1242. /// <param name="e"></param>
  1243. private void label5_Changed(object sender, EventArgs e)
  1244. {
  1245. //this.AppWorkspace.ActiveDocumentWorkspace.HistogramBeta = double.Parse(label5.Text);
  1246. this.scrollMethod();
  1247. }
  1248. /// <summary>
  1249. /// 对比度改变
  1250. /// </summary>
  1251. /// <param name="sender"></param>
  1252. /// <param name="e"></param>
  1253. private void trackBar2_Scroll(object sender, EventArgs e)
  1254. {
  1255. trackBar2Value = trackBar2.Value;
  1256. label6.Text = (trackBar2.Value / 100.0).ToString("f2");
  1257. updateHistogramRect(true);
  1258. }
  1259. /// <summary>
  1260. /// 对比度改变
  1261. /// </summary>
  1262. /// <param name="sender"></param>
  1263. /// <param name="e"></param>
  1264. private void label6_Changed(object sender, EventArgs e)
  1265. {
  1266. //this.AppWorkspace.ActiveDocumentWorkspace.HistogramAlpha = double.Parse(label6.Text);
  1267. this.scrollMethod();
  1268. }
  1269. /// <summary>
  1270. /// gamma改变
  1271. /// gamma值小于1时,会拉伸图像中灰度级较低的区域,同时会压缩灰度级较高的部分
  1272. /// gamma值大于1时,会拉伸图像中灰度级较高的区域,同时会压缩灰度级较低的部分
  1273. /// </summary>
  1274. /// <param name="sender"></param>
  1275. /// <param name="e"></param>
  1276. private void trackBar3_Scroll(object sender, EventArgs e)
  1277. {
  1278. trackBar3Value = trackBar3.Value;
  1279. label7.Text = (trackBar3.Value / 100.0).ToString("f2");
  1280. updateHistogramRect(true);
  1281. }
  1282. /// <summary>
  1283. /// gamma改变
  1284. /// </summary>
  1285. /// <param name="sender"></param>
  1286. /// <param name="e"></param>
  1287. private void label7_Changed(object sender, EventArgs e)
  1288. {
  1289. //this.AppWorkspace.ActiveDocumentWorkspace.HistogramGamma = double.Parse(label7.Text);
  1290. this.scrollMethod();
  1291. }
  1292. /// <summary>
  1293. /// 绘制直方图
  1294. /// </summary>
  1295. /// <param name="hist"></param>
  1296. /// <returns></returns>
  1297. private unsafe void updateHistImg(Mat[] hists)
  1298. {
  1299. if (this.OldMat == null)
  1300. {
  1301. return;
  1302. }
  1303. Mat[] mats = Cv2.Split(this.OldMat);//一张图片,将panda拆分成3个图片装进mat
  1304. Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  1305. Mat[] mats1;
  1306. if (mats.Length < 2)
  1307. mats1 = new Mat[] { mats[0] };//panda的第二个通道,也就是G
  1308. else
  1309. mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  1310. Mat[] mats2;
  1311. if (mats.Length < 3)
  1312. mats2 = new Mat[] { mats[0] };//panda的第三个通道,也就是R
  1313. else
  1314. mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  1315. if (hists == null)
  1316. {
  1317. hists = new Mat[] { new Mat(), new Mat(), new Mat() };//一个矩阵数组,用来接收直方图,记得全部初始化
  1318. int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  1319. int[] channels1 = new int[] { 0 };
  1320. int[] channels2 = new int[] { 0 };
  1321. int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  1322. Rangef[] range = new Rangef[1];//一个通道,范围
  1323. range[0].Start = 0.0F;//从0开始(含)
  1324. range[0].End = 256.0F;//到256结束(不含)
  1325. Mat mask = new Mat();//不做掩码
  1326. Cv2.CalcHist(mats0, channels0, mask, hists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  1327. Cv2.CalcHist(mats1, channels1, mask, hists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  1328. Cv2.CalcHist(mats2, channels2, mask, hists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  1329. if (logButton.BtnSelect)
  1330. {
  1331. //取对数
  1332. for (int j = 0; j < hists.Length; j++)
  1333. {
  1334. List<float> ProbPixel = new List<float>();
  1335. for (int i = 0; i < hists[j].Rows; i++)
  1336. {
  1337. if (((float*)hists[j].Ptr(0))[i] == 0)
  1338. {
  1339. ((float*)hists[j].Ptr(0))[i] = ((float*)hists[j].Ptr(0))[i];
  1340. ProbPixel.Add(0);
  1341. }
  1342. else
  1343. {
  1344. ((float*)hists[j].Ptr(0))[i] = (float)Math.Log10(((float*)hists[j].Ptr(0))[i]/* + 9*/);
  1345. ProbPixel.Add(1);
  1346. }
  1347. }
  1348. double max1jVal = 0;
  1349. double min1jVal = 0;
  1350. //找到直方图中的最大值和最小值
  1351. Cv2.MinMaxLoc(hists[j], out min1jVal, out max1jVal);
  1352. if (min1jVal >= max1jVal)
  1353. {
  1354. continue;
  1355. }
  1356. //归一化到0~255,并根据AxioVision添加偏置值
  1357. for (int i = 0; i < hists[j].Rows; i++)
  1358. {
  1359. ((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);
  1360. }
  1361. }
  1362. }
  1363. if (skipButton.BtnSelect)
  1364. {
  1365. //去掉黑色部分 和 白色部分
  1366. for (int j = 0; j < hists.Length; j++)
  1367. {
  1368. ((float*)hists[j].Ptr(0))[0] = 0;
  1369. ((float*)hists[j].Ptr(0))[255] = 0;
  1370. }
  1371. }
  1372. }
  1373. double max2Val = 0;
  1374. double max1Val = 0;
  1375. double max0Val = 0;
  1376. double minVal = 0;
  1377. //为了更好显示直方图细节,使用4倍尺寸绘制直方图
  1378. int histSize = hists[0].Rows * 4;
  1379. Mat histImg = new Mat(histSize, histSize, MatType.CV_8UC3, new Scalar(255, 255, 255));
  1380. //找到直方图中的最大值和最小值
  1381. Cv2.MinMaxLoc(hists[2], out minVal, out max2Val);
  1382. Cv2.MinMaxLoc(hists[1], out minVal, out max1Val);
  1383. Cv2.MinMaxLoc(hists[0], out minVal, out max0Val);
  1384. double maxVal = Math.Max(max2Val, Math.Max(max0Val, max1Val));
  1385. if (maxVal < 1)
  1386. return;
  1387. // 设置最大峰值为图像高度的90%
  1388. double hpt = 0.9 * histSize;
  1389. //灰度图的显示直方图较为简单,显示一个通道即可
  1390. if (isGray)
  1391. {
  1392. Mat hist = hists[0];
  1393. int lastY2 = histSize - 1;
  1394. for (int h = 0; h < hists[0].Rows; h++)
  1395. {
  1396. int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  1397. int lastY1 = lastY2;
  1398. lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  1399. if (lastY2 < lastY1)
  1400. {
  1401. 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);
  1402. }
  1403. else
  1404. {
  1405. 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);
  1406. }
  1407. }
  1408. }
  1409. //彩度图显示BGR三个通道的直方图
  1410. else
  1411. {
  1412. int lineWidth = 2;
  1413. for (int j = hists.Length - 1; j >= 0; j--)
  1414. {
  1415. Mat hist = hists[j];
  1416. int lastY2 = histSize - 1;
  1417. for (int h = 0; h < hists[0].Rows; h++)
  1418. {
  1419. int intensity = (int)(hist.At<float>(h) * hpt / maxVal);
  1420. int lastY1 = lastY2;
  1421. lastY2 = histSize - intensity - 1 - (hist.At<float>(h) > 0 ? 4 : 0);
  1422. if (h > 0)
  1423. {
  1424. //显示0.5位置的直方图,这样与AxioVision效果更加近似
  1425. int lasty12 = (lastY1 + lastY2) / 2;
  1426. if (lasty12 < lastY1)
  1427. {
  1428. 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);
  1429. }
  1430. else
  1431. {
  1432. 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*/);
  1433. }
  1434. if (lastY2 < lasty12)
  1435. {
  1436. Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lasty12), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lasty12 - 2)), color[j], lineWidth, LineTypes.Link4);
  1437. }
  1438. else
  1439. {
  1440. 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*/);
  1441. }
  1442. }
  1443. else
  1444. {
  1445. //灰度值为0的线的绘制
  1446. if (lastY2 < lastY1)
  1447. {
  1448. Cv2.Line(histImg, new OpenCvSharp.Point(h * 4, lastY1), new OpenCvSharp.Point(h * 4, Math.Min(lastY2, lastY1 - 2)), color[j], lineWidth, LineTypes.Link4);
  1449. }
  1450. else
  1451. {
  1452. 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*/);
  1453. }
  1454. }
  1455. }
  1456. }
  1457. }
  1458. this.pictureBox1.BackgroundImage/*Image*/ = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  1459. }
  1460. /// <summary>
  1461. /// 测试曲线拟合的代码
  1462. /// </summary>
  1463. private void testCurveFit()
  1464. {
  1465. //创建用于绘制的深蓝色背景图像
  1466. 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));
  1467. //输入拟合点
  1468. List<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();// std::vector<cv::Point> points;
  1469. points.Add(new OpenCvSharp.Point(0, 254));
  1470. points.Add(new OpenCvSharp.Point(127, 222/*32*/));
  1471. points.Add(new OpenCvSharp.Point(254, 0));
  1472. //points.Add(new OpenCvSharp.Point(100, 58));
  1473. //points.Add(new OpenCvSharp.Point(150, 70));
  1474. //points.Add(new OpenCvSharp.Point(200, 90));
  1475. ////points.push_back(cv::Point(100., 58.)); points.push_back(cv::Point(150., 70.)); points.push_back(cv::Point(200., 90.));
  1476. //points.Add(new OpenCvSharp.Point(252, 140));
  1477. //points.Add(new OpenCvSharp.Point(300, 220));
  1478. //points.Add(new OpenCvSharp.Point(350, 400));
  1479. //points.push_back(cv::Point(252., 140.)); points.push_back(cv::Point(300., 220.)); points.push_back(cv::Point(350., 400.));
  1480. List<List<OpenCvSharp.Point>> pointsIn = new List<List<OpenCvSharp.Point>>()
  1481. {
  1482. points
  1483. };
  1484. //将拟合点绘制到空白图上
  1485. for (int i = 0; i < points.Count; i++)
  1486. {
  1487. Cv2.Circle(image, points[i].X, points[i].Y, 5, new Scalar(0, 0, 255), 2, LineTypes.Link8, 0);
  1488. //cv::circle(image, points[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
  1489. }
  1490. //绘制折线
  1491. 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);
  1492. Mat A = new Mat(3 + 1/*480*/, 1/*640*/, MatType.CV_64FC1, new Scalar(0));// cv::Mat A;
  1493. polynomial_curve_fit(points.ToArray(), 3, A);
  1494. //std::cout << "A = " << A << std::endl;
  1495. List<OpenCvSharp.Point> points_fitted = new List<OpenCvSharp.Point>(); //std::vector<cv::Point> points_fitted;
  1496. List<double> dataFitted = new List<double>();
  1497. dataFitted.Add(A.At<double>(0, 0));
  1498. dataFitted.Add(A.At<double>(1, 0));
  1499. dataFitted.Add(A.At<double>(2, 0));
  1500. dataFitted.Add(A.At<double>(3, 0));
  1501. for (int x = 0; x < 255; x++)
  1502. {
  1503. 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);
  1504. // 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);
  1505. points_fitted.Add(new OpenCvSharp.Point(x, y));
  1506. // points_fitted.push_back(cv::Point(x, y));
  1507. }
  1508. List<List<OpenCvSharp.Point>> points_fittedIn = new List<List<OpenCvSharp.Point>>()
  1509. {
  1510. points_fitted
  1511. };
  1512. //黄色线表示拟合后的曲线,成功
  1513. 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);
  1514. Cv2.ImShow("image", image);// cv::imshow("image", image);
  1515. //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  1516. }
  1517. /// <summary>
  1518. /// 将拟合点绘制到空白图上
  1519. /// //原文链接:https://blog.csdn.net/guduruyu/article/details/72866144
  1520. /// </summary>
  1521. /// <param name="key_point">拟合点</param>
  1522. /// <param name="n">拟合矩阵的??数量</param>
  1523. /// <param name="A">空白图</param>
  1524. /// <returns></returns>
  1525. private unsafe bool polynomial_curve_fit(OpenCvSharp.Point[] key_point, int n, Mat A)
  1526. {
  1527. //Number of key points
  1528. int N = key_point.Length;
  1529. //构造矩阵X
  1530. 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);
  1531. for (int i = 0; i < n + 1; i++)
  1532. {
  1533. for (int j = 0; j < n + 1; j++)
  1534. {
  1535. ((double*)X.Ptr(i))[j] = 0;//111
  1536. for (int k = 0; k < N; k++)
  1537. {
  1538. ((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);
  1539. }
  1540. }
  1541. }
  1542. //构造矩阵Y
  1543. Mat Y = new Mat(n + 1, 1, MatType.CV_64FC1, new Scalar(0));// cv::Mat Y = cv::Mat::zeros(n + 1, 1, CV_64FC1);
  1544. for (int i = 0; i < n + 1; i++)
  1545. {
  1546. ((double*)Y.Ptr(i))[0] = 0;//111
  1547. for (int k = 0; k < N; k++)
  1548. {
  1549. ((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;
  1550. }
  1551. }
  1552. //A = new Mat(n + 1, 1, MatType.CV_64FC1, new Scalar(0));// A = cv::Mat::zeros(n + 1, 1, CV_64FC1);
  1553. //List<double> dataFitted = new List<double>();
  1554. //dataFitted.Add(Y.At<double>(0, 0));
  1555. //dataFitted.Add(Y.At<double>(1, 0));
  1556. //dataFitted.Add(Y.At<double>(2, 0));
  1557. //dataFitted.Add(Y.At<double>(3, 0));
  1558. //for (int i = 0; i < n + 1; i++)
  1559. //{
  1560. // for (int j = 0; j < n + 1; j++)
  1561. // {
  1562. // dataFitted.Add(X.At<double>(i, j));
  1563. // }
  1564. //}
  1565. //求解矩阵A
  1566. Cv2.Solve(X, Y, A, DecompTypes.LU);//Cv2.Solve(X, Y, A, DecompTypes.LU); cv::solve(X, Y, A, cv::DECOMP_LU);
  1567. //dataFitted.Add(A.At<double>(0, 0));
  1568. //dataFitted.Add(A.At<double>(1, 0));
  1569. //dataFitted.Add(A.At<double>(2, 0));
  1570. //dataFitted.Add(A.At<double>(3, 0));
  1571. return true;
  1572. }
  1573. /// <summary>
  1574. /// 通过颜色通道去除像素点的千分比计算有效阈值
  1575. /// </summary>
  1576. /// <param name="hists"></param>
  1577. /// <param name="percentValue"></param>
  1578. /// <returns></returns>
  1579. private OpenCvSharp.Point getStartIndex(Mat mat, Mat[] hists, float percentValue)
  1580. {
  1581. //灰度化图片取第一通道
  1582. Mat histGray = hists[0];
  1583. //彩色图片取灰度化后的通道
  1584. if (!isGray)
  1585. {
  1586. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(0, histGray.Rows);
  1587. //计算三次
  1588. OpenCvSharp.Point startIndex0 = this.getStartRange(mat, hists[0], percentValue);
  1589. OpenCvSharp.Point startIndex1 = this.getStartRange(mat, hists[1], percentValue);
  1590. OpenCvSharp.Point startIndex2 = this.getStartRange(mat, hists[2], percentValue);
  1591. startIndex.X = Math.Min(startIndex0.X, Math.Min(startIndex1.X, startIndex2.X));
  1592. startIndex.Y = Math.Max(startIndex0.Y, Math.Max(startIndex1.Y, startIndex2.Y));
  1593. startIndex.Y = Math.Min(255 - 1, startIndex.Y);
  1594. startIndex.X = Math.Max(startIndex.X, 1);
  1595. startIndex.Y = Math.Max(startIndex.X + 1, startIndex.Y);
  1596. return startIndex;
  1597. }
  1598. return this.getStartRange(mat, histGray, percentValue);
  1599. }
  1600. private OpenCvSharp.Point getStartRange(Mat mat, Mat histGray, float percentValue)
  1601. {
  1602. if (this.OldMat == null)
  1603. {
  1604. return new OpenCvSharp.Point(1, 254); ;
  1605. }
  1606. //计算灰度分布密度
  1607. float totalPoints = this.OldMat.Cols * this.OldMat.Rows;
  1608. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(0, histGray.Rows);
  1609. bool foundStartTag = false;
  1610. bool foundEndTag = false;
  1611. //根据累计直方图分布计算左右阈值
  1612. float equalizeHists = 0;
  1613. for (int i = 0; i < histGray.Rows; ++i)
  1614. {
  1615. equalizeHists += ((float)(histGray.At<float>(i) / (totalPoints * 1.0))) * 1000;
  1616. if (!foundStartTag && equalizeHists > percentValue)
  1617. {
  1618. foundStartTag = true;
  1619. startIndex.X = i;
  1620. }
  1621. else if (equalizeHists >= 1000 - percentValue)
  1622. {
  1623. foundEndTag = true;
  1624. startIndex.Y = i;
  1625. }
  1626. if (foundStartTag && foundEndTag)
  1627. break;
  1628. }
  1629. startIndex.Y = Math.Min(255 - 1, startIndex.Y);
  1630. startIndex.X = Math.Max(startIndex.X, 1);
  1631. startIndex.Y = Math.Max(startIndex.X + 1, startIndex.Y);
  1632. return startIndex;
  1633. }
  1634. /// <summary>
  1635. /// 更新直方图特征曲线
  1636. /// </summary>
  1637. /// <param name="updateThreePoints">是否需要更新三个控制点的位置</param>
  1638. private void updateHistogramRect(bool updateThreePoints)
  1639. {
  1640. //为了更好显示直方图细节,使用4倍尺寸绘制直方图
  1641. int histSize = 256/*oldHists[0].Rows*/ * 4;
  1642. //创建用于绘制的深蓝色背景图像
  1643. Mat image = new Mat(histSize, histSize, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  1644. //输入拟合点
  1645. List<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();
  1646. //根据亮度和对比度计算左右阈值
  1647. 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);
  1648. int grayMax = (int)((256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) - double.Parse(label5.Text) * 510.0) / 2.0);
  1649. if (grayMin >= grayMax)
  1650. {
  1651. return;
  1652. }
  1653. if (updateThreePoints)
  1654. {
  1655. ucTrackBar1.Value1 = grayMin;
  1656. ucTrackBar1.Value3 = grayMax;
  1657. //ucTrackBar1.Value2 = (float)((grayMin + grayMax) / 2.0);
  1658. }
  1659. //gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  1660. double gamma = Math.Max(0.01, double.Parse(label7.Text));
  1661. //计算Value2
  1662. ucTrackBar1.Value2 = (float)Math.Max(grayMin, Math.Min(grayMax, Math.Pow(0.5, 1.0 / gamma) * (grayMax - grayMin) + grayMin));
  1663. ucTrackBar1.Refresh();
  1664. int lastY2 = histSize + 0;// histSize - 1;
  1665. for (int h = 0; h <= 256; h++)
  1666. {
  1667. if (h < grayMin)
  1668. {
  1669. points.Add(new OpenCvSharp.Point(h * 4, lastY2));
  1670. continue;
  1671. }
  1672. else if (h > grayMax)
  1673. {
  1674. lastY2 = -1;// 0;
  1675. points.Add(new OpenCvSharp.Point(h * 4, lastY2));
  1676. continue;
  1677. }
  1678. int lastY1 = (int)Math.Round((1.0 - Math.Pow((h - grayMin) * 1.0 / (grayMax - grayMin), gamma)) * (histSize + 1/*histSize - 1*/)) - 1;
  1679. lastY1 = Math.Min(lastY2, Math.Max(0, lastY1));
  1680. if (lastY2 == lastY1)
  1681. {
  1682. if (h == 0 || h == 256)
  1683. {
  1684. points.Add(new OpenCvSharp.Point(h * 4, lastY1));
  1685. }
  1686. }
  1687. else
  1688. {
  1689. points.Add(new OpenCvSharp.Point(h * 4, lastY1));
  1690. lastY2 = lastY1;
  1691. }
  1692. }
  1693. lastY2 = histSize + 0;// histSize - 1;
  1694. //将第一个点的位置设置最底部,保证曲线平滑性
  1695. //if (points[0].X > 4 && points[0].Y < lastY2)
  1696. //{
  1697. // points.Insert(0, new OpenCvSharp.Point(points[0].X - 4, lastY2));
  1698. //}
  1699. List<List<OpenCvSharp.Point>> pointsIn = new List<List<OpenCvSharp.Point>>()
  1700. {
  1701. points
  1702. };
  1703. //绘制折线
  1704. 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);
  1705. //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);
  1706. Mat A = new Mat(3 + 1, 1, MatType.CV_64FC1, new Scalar(0));
  1707. polynomial_curve_fit(points.ToArray(), 3, A);
  1708. List<OpenCvSharp.Point> points_fitted = new List<OpenCvSharp.Point>(); //std::vector<cv::Point> points_fitted;
  1709. List<double> dataFitted = new List<double>();
  1710. dataFitted.Add(A.At<double>(0, 0));
  1711. dataFitted.Add(A.At<double>(1, 0));
  1712. dataFitted.Add(A.At<double>(2, 0));
  1713. dataFitted.Add(A.At<double>(3, 0));
  1714. for (int x = 0; x < histSize + 1; x++)
  1715. {
  1716. if (x < grayMin * 4)
  1717. {
  1718. points_fitted.Add(new OpenCvSharp.Point(x, lastY2));
  1719. continue;
  1720. }
  1721. else if (x > grayMax * 4)
  1722. {
  1723. lastY2 = -1;// 0;
  1724. points_fitted.Add(new OpenCvSharp.Point(x, lastY2));
  1725. continue;
  1726. }
  1727. 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);
  1728. points_fitted.Add(new OpenCvSharp.Point(x, y));
  1729. }
  1730. //List<List<OpenCvSharp.Point>> points_fittedIn = new List<List<OpenCvSharp.Point>>()
  1731. //{
  1732. // points_fitted
  1733. //};
  1734. ////绘制折线
  1735. //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);
  1736. this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);
  1737. // //黄色线表示拟合后的曲线,成功
  1738. // 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);
  1739. // Cv2.ImShow("image", image);// cv::imshow("image", image);
  1740. //this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(histImg);
  1741. }
  1742. /// <summary>
  1743. ///
  1744. /// </summary>
  1745. /// <param name="oldmat">原图</param>
  1746. /// <param name="label5_Text">亮度</param>
  1747. /// <param name="label6_Text">对比度</param>
  1748. /// <param name="label7_Text">gamma值</param>
  1749. /// <returns></returns>
  1750. public static Mat scrollMethod(Mat oldmat, string label5_Text, string label6_Text, string label7_Text)
  1751. {
  1752. if (oldmat == null)
  1753. {
  1754. return null;
  1755. }
  1756. Mat[] mats = Cv2.Split(oldmat);//一张图片,将panda拆分成3个图片装进mat
  1757. bool isGray = true;
  1758. /// <summary>
  1759. /// 一个矩阵数组,用来接收直方图,记得全部初始化
  1760. /// </summary>
  1761. Mat[] oldHists = new Mat[] { new Mat(), new Mat(), new Mat() };
  1762. Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
  1763. Mat[] mats1;
  1764. if (mats.Length < 2)
  1765. mats1 = new Mat[] { mats[0] };//panda的第二个通道,也就是G
  1766. else
  1767. mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
  1768. Mat[] mats2;
  1769. if (mats.Length < 3)
  1770. {
  1771. mats2 = new Mat[] { mats[0] };//panda的第三个通道,也就是R
  1772. mats = new Mat[] { mats0[0], mats0[0], mats0[0] };
  1773. }
  1774. else
  1775. mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
  1776. int[] channels0 = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
  1777. int[] channels1 = new int[] { 0 };
  1778. int[] channels2 = new int[] { 0 };
  1779. int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
  1780. Rangef[] range = new Rangef[1];//一个通道,范围
  1781. range[0].Start = 0.0F;//从0开始(含)
  1782. range[0].End = 256.0F;//到256结束(不含)
  1783. Mat mask = new Mat();//不做掩码
  1784. Cv2.CalcHist(mats0, channels0, mask, oldHists[0], 1, histsize, range);//对被拆分的图片单独进行计算
  1785. Cv2.CalcHist(mats1, channels1, mask, oldHists[1], 1, histsize, range);//对被拆分的图片单独进行计算
  1786. Cv2.CalcHist(mats2, channels2, mask, oldHists[2], 1, histsize, range);//对被拆分的图片单独进行计算
  1787. for (int h = 0; h < oldHists[0].Rows; h++)
  1788. {
  1789. for (int j = oldHists.Length - 1; j >= 1; j--)
  1790. {
  1791. if (oldHists[j].At<float>(h) != oldHists[0].At<float>(h))
  1792. {
  1793. isGray = false;
  1794. break;
  1795. }
  1796. }
  1797. if (!isGray)
  1798. break;
  1799. }
  1800. //根据亮度和对比度计算左右阈值
  1801. 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);
  1802. int grayMax = (int)((256.0 / (double.Parse(label6_Text) == 0 ? 0.01 : double.Parse(label6_Text)) - double.Parse(label5_Text) * 510.0) / 2.0);
  1803. if (grayMin >= grayMax)
  1804. {
  1805. return null;
  1806. }
  1807. Mat dst = new Mat();
  1808. //如果是灰度化图片,则只需计算一个通道。对灰度值进行映射,BGR根据左右阈值做缩放操作
  1809. if (isGray)
  1810. {
  1811. Cv2.Min(mats[0], new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMax)), dst);
  1812. Cv2.Max(dst, new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMin)), dst);
  1813. Cv2.Normalize(dst, dst, 0, 255, NormTypes.MinMax);
  1814. }
  1815. else
  1816. {
  1817. if (mats.Length < oldHists.Length)
  1818. for (int j = 0; j < oldHists.Length; j++)
  1819. {
  1820. Cv2.Min(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMax)), mats[j]);
  1821. Cv2.Max(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMin)), mats[j]);
  1822. Cv2.Normalize(mats[j], mats[j], 0, 255, NormTypes.MinMax);
  1823. }
  1824. else
  1825. for (int j = 0; j < oldHists.Length; j++)
  1826. {
  1827. Cv2.Min(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMax)), mats[j]);
  1828. Cv2.Max(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMin)), mats[j]);
  1829. Cv2.Normalize(mats[j], mats[j], 0, 255, NormTypes.MinMax);
  1830. }
  1831. Cv2.Merge(mats, dst);
  1832. }
  1833. //灰度归一化
  1834. dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  1835. //gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  1836. Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7_Text)), dst);
  1837. dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
  1838. //Document document = Document.FromImage(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  1839. //this.AppWorkspace.ActiveDocumentWorkspace.setDoc(document, false);
  1840. //this.AppWorkspace.ActiveDocumentWorkspace.Refresh();
  1841. ////this.AppWorkspace.ActiveDocumentWorkspace.CompositionSurface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  1842. #region 均衡化的方法备份
  1843. ////对灰度值进行映射(均衡化)
  1844. //float[] totalPoints = new float[] { oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows };
  1845. ////去掉黑色部分 和 白色部分
  1846. //for (int j = 0; j < oldHists.Length; j++)
  1847. //{
  1848. // for (int i = 0; i < grayMin; i++)
  1849. // {
  1850. // totalPoints[j] = totalPoints[j] - oldHists[j].At<float>(i);
  1851. // }
  1852. // for (int i = grayMax; i < oldHists[j].Rows; i++)
  1853. // {
  1854. // totalPoints[j] = totalPoints[j] - oldHists[j].At<float>(i);
  1855. // }
  1856. //}
  1857. //for (int j = 0; j < (isGray ? 1 : oldHists.Length); j++)
  1858. //{
  1859. // //计算灰度分布密度
  1860. // //List<float> ProbPixel = new List<float>();
  1861. // //计算累计直方图分布
  1862. // List<float> equalizeHists = new List<float>();
  1863. // Mat hist = oldHists[j];
  1864. // //计算累计直方图分布
  1865. // for (int i = 0; i < hist.Rows; ++i)
  1866. // {
  1867. // //去掉黑色部分 和 白色部分
  1868. // if (i < grayMin || i > grayMax)
  1869. // {
  1870. // if (i == 0)
  1871. // {
  1872. // equalizeHists.Add(0);
  1873. // }
  1874. // else
  1875. // {
  1876. // equalizeHists.Add(equalizeHists[i - 1]);
  1877. // }
  1878. // }
  1879. // else if (i == 0)
  1880. // {
  1881. // equalizeHists.Add((float)(hist.At<float>(i) / (totalPoints[j] * 1.0)));
  1882. // }
  1883. // else
  1884. // {
  1885. // equalizeHists.Add(equalizeHists[i - 1] + (float)(hist.At<float>(i) / (totalPoints[j] * 1.0)));
  1886. // }
  1887. // }
  1888. // //累计分布取整
  1889. // for (int i = 0; i < equalizeHists.Count; ++i)
  1890. // {
  1891. // float numHist = equalizeHists[i];
  1892. // equalizeHists[i] = Math.Min(255, (int)(numHist * 255.0 + 0.5));
  1893. // }
  1894. // for (int y = 0; y < h; ++y)
  1895. // //对灰度值进行映射,BGR根据左右阈值做缩放操作
  1896. // {
  1897. // byte* imageData = (byte*)(mats[j].Ptr(y));
  1898. // //对灰度值进行映射
  1899. // for (int x = 0; x < w; ++x)
  1900. // {
  1901. // int oldvalue = imageData[x];
  1902. // if (oldvalue < grayMin)
  1903. // {
  1904. // imageData[x] = 0;
  1905. // }
  1906. // else if (oldvalue > grayMax)
  1907. // {
  1908. // imageData[x] = 255;
  1909. // }
  1910. // else
  1911. // {
  1912. // imageData[x] = (byte)equalizeHists[oldvalue];
  1913. // }
  1914. // }
  1915. // }
  1916. //}
  1917. //Mat dst = new Mat();
  1918. ////灰度归一化
  1919. //if (isGray)
  1920. //{
  1921. // mats[0].ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  1922. //}
  1923. //else
  1924. //{
  1925. // Cv2.Merge(mats, dst);
  1926. // dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  1927. //}
  1928. ////gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  1929. //Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7.Text)), dst);
  1930. //dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
  1931. //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  1932. #endregion
  1933. return dst;
  1934. }
  1935. /// <summary>
  1936. /// 根据亮度、对比度、gamma对图片进行处理
  1937. /// </summary>
  1938. private void scrollMethod()
  1939. {
  1940. trackBar1Value = trackBar1.Value;
  1941. trackBar2Value = trackBar2.Value;
  1942. trackBar3Value = trackBar3.Value;
  1943. //if (this.OldMat == null)
  1944. //{
  1945. // return;
  1946. //}
  1947. //Mat[] mats = Cv2.Split(this.OldMat);//一张图片,将panda拆分成3个图片装进mat
  1948. ////根据亮度和对比度计算左右阈值
  1949. //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);
  1950. //int grayMax = (int)((256.0 / (double.Parse(label6.Text) == 0 ? 0.01 : double.Parse(label6.Text)) - double.Parse(label5.Text) * 510.0) / 2.0);
  1951. //if (grayMin >= grayMax)
  1952. //{
  1953. // return;
  1954. //}
  1955. //Mat dst = new Mat();
  1956. ////如果是灰度化图片,则只需计算一个通道。对灰度值进行映射,BGR根据左右阈值做缩放操作
  1957. //if (isGray)
  1958. //{
  1959. // Cv2.Min(mats[0], new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMax)), dst);
  1960. // Cv2.Max(dst, new Mat(mats[0].Rows, mats[0].Cols, MatType.CV_8UC1, new Scalar(grayMin)), dst);
  1961. // Cv2.Normalize(dst, dst, 0, 255, NormTypes.MinMax);
  1962. //}
  1963. //else
  1964. //{
  1965. // for (int j = 0; j < oldHists.Length; j++)
  1966. // {
  1967. // Cv2.Min(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMax)), mats[j]);
  1968. // Cv2.Max(mats[j], new Mat(mats[j].Rows, mats[j].Cols, MatType.CV_8UC1, new Scalar(grayMin)), mats[j]);
  1969. // Cv2.Normalize(mats[j], mats[j], 0, 255, NormTypes.MinMax);
  1970. // }
  1971. // Cv2.Merge(mats, dst);
  1972. //}
  1973. ////灰度归一化
  1974. //dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  1975. ////gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  1976. //Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7.Text)), dst);
  1977. //dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
  1978. //Document document = Document.FromImage(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  1979. //this.AppWorkspace.ActiveDocumentWorkspace.setDoc(document, false);
  1980. //this.AppWorkspace.ActiveDocumentWorkspace.Refresh();
  1981. ////this.AppWorkspace.ActiveDocumentWorkspace.CompositionSurface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  1982. #region 均衡化的方法备份
  1983. ////对灰度值进行映射(均衡化)
  1984. //float[] totalPoints = new float[] { oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows, oldMat.Cols * oldMat.Rows };
  1985. ////去掉黑色部分 和 白色部分
  1986. //for (int j = 0; j < oldHists.Length; j++)
  1987. //{
  1988. // for (int i = 0; i < grayMin; i++)
  1989. // {
  1990. // totalPoints[j] = totalPoints[j] - oldHists[j].At<float>(i);
  1991. // }
  1992. // for (int i = grayMax; i < oldHists[j].Rows; i++)
  1993. // {
  1994. // totalPoints[j] = totalPoints[j] - oldHists[j].At<float>(i);
  1995. // }
  1996. //}
  1997. //for (int j = 0; j < (isGray ? 1 : oldHists.Length); j++)
  1998. //{
  1999. // //计算灰度分布密度
  2000. // //List<float> ProbPixel = new List<float>();
  2001. // //计算累计直方图分布
  2002. // List<float> equalizeHists = new List<float>();
  2003. // Mat hist = oldHists[j];
  2004. // //计算累计直方图分布
  2005. // for (int i = 0; i < hist.Rows; ++i)
  2006. // {
  2007. // //去掉黑色部分 和 白色部分
  2008. // if (i < grayMin || i > grayMax)
  2009. // {
  2010. // if (i == 0)
  2011. // {
  2012. // equalizeHists.Add(0);
  2013. // }
  2014. // else
  2015. // {
  2016. // equalizeHists.Add(equalizeHists[i - 1]);
  2017. // }
  2018. // }
  2019. // else if (i == 0)
  2020. // {
  2021. // equalizeHists.Add((float)(hist.At<float>(i) / (totalPoints[j] * 1.0)));
  2022. // }
  2023. // else
  2024. // {
  2025. // equalizeHists.Add(equalizeHists[i - 1] + (float)(hist.At<float>(i) / (totalPoints[j] * 1.0)));
  2026. // }
  2027. // }
  2028. // //累计分布取整
  2029. // for (int i = 0; i < equalizeHists.Count; ++i)
  2030. // {
  2031. // float numHist = equalizeHists[i];
  2032. // equalizeHists[i] = Math.Min(255, (int)(numHist * 255.0 + 0.5));
  2033. // }
  2034. // for (int y = 0; y < h; ++y)
  2035. // //对灰度值进行映射,BGR根据左右阈值做缩放操作
  2036. // {
  2037. // byte* imageData = (byte*)(mats[j].Ptr(y));
  2038. // //对灰度值进行映射
  2039. // for (int x = 0; x < w; ++x)
  2040. // {
  2041. // int oldvalue = imageData[x];
  2042. // if (oldvalue < grayMin)
  2043. // {
  2044. // imageData[x] = 0;
  2045. // }
  2046. // else if (oldvalue > grayMax)
  2047. // {
  2048. // imageData[x] = 255;
  2049. // }
  2050. // else
  2051. // {
  2052. // imageData[x] = (byte)equalizeHists[oldvalue];
  2053. // }
  2054. // }
  2055. // }
  2056. //}
  2057. //Mat dst = new Mat();
  2058. ////灰度归一化
  2059. //if (isGray)
  2060. //{
  2061. // mats[0].ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  2062. //}
  2063. //else
  2064. //{
  2065. // Cv2.Merge(mats, dst);
  2066. // dst.ConvertTo(dst, MatType.CV_64F, 1.0 / 255, 0);
  2067. //}
  2068. ////gamma运算,gamma值根据AxioVision对比 取最小值0.01进行计算
  2069. //Cv2.Pow(dst, Math.Max(0.01, double.Parse(label7.Text)), dst);
  2070. //dst.ConvertTo(dst, MatType.CV_8U, 255, 0);
  2071. //this.AppWorkspace.ActiveDocumentWorkspace.SurfaceBox.Surface = Surface.CopyFromBitmap(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst));
  2072. #endregion
  2073. }
  2074. /// <summary>
  2075. /// 拖动左侧三角形
  2076. /// </summary>
  2077. /// <param name="sender"></param>
  2078. /// <param name="e"></param>
  2079. private void ucTrackBar1_Value1Changed(object sender, EventArgs e)
  2080. {
  2081. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(ucTrackBar1.Value1, ucTrackBar1.Value3);
  2082. //计算对比度
  2083. label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
  2084. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  2085. //计算亮度
  2086. label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
  2087. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  2088. //备注:这里是可以优化用户体验的地方(避免操作事件引起多次计算发生)
  2089. //this.scrollMethod();
  2090. updateHistogramRect(false);
  2091. }
  2092. /// <summary>
  2093. /// 拖动中间三角形
  2094. /// </summary>
  2095. /// <param name="sender"></param>
  2096. /// <param name="e"></param>
  2097. private void ucTrackBar1_Value2Changed(object sender, EventArgs e)
  2098. {
  2099. //计算gamma值
  2100. double gamma = 1.0 / Math.Log((ucTrackBar1.Value2 - ucTrackBar1.Value1) / (ucTrackBar1.Value3 - ucTrackBar1.Value1), 0.5);
  2101. gamma = Math.Max(0.01, gamma);
  2102. this.trackBar3.Value = Math.Min(299, (int)(gamma * 100));//备注:需要与AxioVision进行比较效果,调试一致
  2103. label7.Text = gamma.ToString("f2");
  2104. //备注:这里是可以优化用户体验的地方(避免操作事件引起多次计算发生)
  2105. updateHistogramRect(false);
  2106. }
  2107. /// <summary>
  2108. /// 拖动右侧三角形
  2109. /// </summary>
  2110. /// <param name="sender"></param>
  2111. /// <param name="e"></param>
  2112. private void ucTrackBar1_Value3Changed(object sender, EventArgs e)
  2113. {
  2114. OpenCvSharp.Point startIndex = new OpenCvSharp.Point(ucTrackBar1.Value1, ucTrackBar1.Value3);// this.getStartIndex(oldMat, oldHists, (float)numericUpDown1.Value);
  2115. //计算对比度
  2116. label6.Text = (256.0 / (startIndex.Y - startIndex.X)).ToString("f2");
  2117. trackBar2.Value = Math.Min(trackBar2.Maximum, (int)(double.Parse(label6.Text) * 100));
  2118. //计算亮度
  2119. label5.Text = ((0 - startIndex.X - startIndex.Y) / 510.0).ToString("f2");
  2120. trackBar1.Value = (int)(double.Parse(label5.Text) * 100);
  2121. //this.scrollMethod();
  2122. updateHistogramRect(false);
  2123. }
  2124. }
  2125. }