ImageRGBanalysis.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.IO;
  6. namespace SHJX.Service.Common.Camera
  7. {
  8. public class ImageRGBanalysis
  9. {
  10. public ImageRGBanalysis()
  11. {
  12. IsLog = false;
  13. }
  14. #region properties
  15. /// <summary>
  16. /// 是否写Log
  17. /// </summary>
  18. public bool IsLog { get; set; }
  19. #endregion
  20. #region methods
  21. public Bitmap CropImage(Bitmap srcImage, Rectangle rcCrop)
  22. {
  23. BitmapData bmpData = srcImage.LockBits(rcCrop, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  24. Bitmap dstImage = new(rcCrop.Width, rcCrop.Height, bmpData.Stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, bmpData.Scan0);
  25. srcImage.UnlockBits(bmpData);
  26. return dstImage;
  27. }
  28. public int GetTotalFromImage(Bitmap srcImage, Rectangle rcCrop, string strChannel = "G")
  29. {
  30. int channel = 0; // 要提取的颜色通道
  31. channel = strChannel.ToUpper() switch
  32. {
  33. "B" => 0,
  34. "G" => 1,
  35. "R" => 2,
  36. _ => 0,
  37. };
  38. if (srcImage.PixelFormat != PixelFormat.Format24bppRgb)
  39. {
  40. return 0; // 暂时只处理24bit图像
  41. }
  42. BitmapData bmpData = srcImage.LockBits(rcCrop, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  43. int totalVal = 0; // 用于统计指定颜色总和
  44. unsafe
  45. {
  46. byte* pSrc = (byte*)(void*)bmpData.Scan0;
  47. for (int i = 0; i < bmpData.Height; i++)
  48. {
  49. for (int j = 0; j < bmpData.Width; j++)
  50. {
  51. totalVal += *(pSrc + bmpData.Stride * i + j * 3 + channel);
  52. }
  53. }
  54. }
  55. srcImage.UnlockBits(bmpData);
  56. return totalVal;
  57. }
  58. /// <summary>
  59. /// 写图像指定区域的RGB值到日志文件中
  60. /// </summary>
  61. /// <param name="srcImage">图像像素</param>
  62. /// <param name="rcCrop">处理区域</param>
  63. /// <param name="title">日志标题</param>
  64. public string WriteRGBlog(Bitmap srcImage, Rectangle rcCrop, string title)
  65. {
  66. if (srcImage == null ||
  67. srcImage.PixelFormat != PixelFormat.Format24bppRgb)
  68. {
  69. return string.Empty; // 暂时只处理24bit图像
  70. }
  71. BitmapData bmpData = srcImage.LockBits(rcCrop, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  72. int vr = 0, vg = 0, vb = 0; // 单个像素点
  73. string strr = "A:\r\n";
  74. string strg = "B:\r\n";
  75. string strb = "C:\r\n";
  76. unsafe
  77. {
  78. List<Color> img = new(); // 用于过滤的像素数据
  79. byte* pSrc = (byte*)(void*)bmpData.Scan0;
  80. for (int i = 0; i < bmpData.Height; i++)
  81. {
  82. for (int j = 0; j < bmpData.Width; j++)
  83. {
  84. vb = *(pSrc + bmpData.Stride * i + j * 3 + 0);
  85. vg = *(pSrc + bmpData.Stride * i + j * 3 + 1);
  86. vr = *(pSrc + bmpData.Stride * i + j * 3 + 2);
  87. strr = string.Format("{0}{1},", strr, vr.ToString().PadLeft(3, ' '));
  88. strg = string.Format("{0}{1},", strg, vg.ToString().PadLeft(3, ' '));
  89. strb = string.Format("{0}{1},", strb, vb.ToString().PadLeft(3, ' '));
  90. }
  91. strr = string.Format("{0}\r\n", strr);
  92. strg = string.Format("{0}\r\n", strg);
  93. strb = string.Format("{0}\r\n", strb);
  94. }
  95. }
  96. srcImage.UnlockBits(bmpData);
  97. return strb;
  98. }
  99. /// <summary>
  100. /// 在左右偏移范围内重新定位目标区域的坐标位置:连续4点相减都满足小于阈值
  101. /// </summary>
  102. /// <param name="srcImage">图像像素数据</param>
  103. /// <param name="rcCrop">目标区域</param>
  104. /// <param name="offset">左右偏移查找范围</param>
  105. /// <param name="threhold">连续两点之差阈值</param>
  106. /// <returns></returns>
  107. public Rectangle GetRoiPos2(Bitmap srcImage, Rectangle rcCrop, int offset = 10, int threhold = 3)
  108. {
  109. Rectangle newRoi = new(rcCrop.Location, rcCrop.Size);
  110. if (srcImage.PixelFormat != PixelFormat.Format24bppRgb)
  111. {
  112. return newRoi; // 暂时只处理24bit图像
  113. }
  114. BitmapData bmpData = srcImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  115. int vg1 = 0, vg2 = 0, vg3, vg4 = 0;//, vg5 = 0;
  116. int rowno = (rcCrop.Top + rcCrop.Bottom) / 2;
  117. int left = Math.Max(0, (rcCrop.Left - offset));
  118. int right = Math.Min(srcImage.Width - 1, (rcCrop.Right + offset));
  119. unsafe
  120. {
  121. byte* pSrc = (byte*)(void*)bmpData.Scan0;
  122. for (int j = left; j < right; j++)
  123. {
  124. int istart = bmpData.Stride * rowno + j * 3 + 1;
  125. vg1 = *(pSrc + istart + 3 * 0);
  126. vg2 = *(pSrc + istart + 3 * 1);
  127. vg3 = *(pSrc + istart + 3 * 2);
  128. vg4 = *(pSrc + istart + 3 * 3);
  129. //vg5 = *(pSrc + istart + 3 * 4);
  130. if (vg2 - vg1 >= threhold &&
  131. vg3 - vg2 >= threhold &&
  132. vg4 - vg3 >= threhold)
  133. {
  134. left = j;
  135. break;
  136. }
  137. }
  138. for (int j = right; j > left; j--)
  139. {
  140. int istart = bmpData.Stride * rowno + j * 3 + 1;
  141. vg1 = *(pSrc + istart - 3 * 0);
  142. vg2 = *(pSrc + istart - 3 * 1);
  143. vg3 = *(pSrc + istart - 3 * 2);
  144. vg4 = *(pSrc + istart - 3 * 3);
  145. //vg5 = *(pSrc + istart - 3 * 4);
  146. if (vg2 - vg1 >= threhold &&
  147. vg3 - vg2 >= threhold &&
  148. vg4 - vg3 >= threhold)
  149. {
  150. right = j;
  151. break;
  152. }
  153. }
  154. }
  155. srcImage.UnlockBits(bmpData);
  156. newRoi.X = ((left + right) - rcCrop.Width) / 2 + 1;
  157. //PublicDatas.LogProgram.Info(string.Format("found roi left={0}, right={1}", left, right));
  158. return newRoi;
  159. }
  160. /// <summary>
  161. /// 以指定值threhold为阈值,找到上下左右边界,然后以此为中心返回新的目标矩形区域
  162. /// </summary>
  163. /// <param name="srcImage"></param>
  164. /// <param name="rcCrop"></param>
  165. /// <param name="offset"></param>
  166. /// <param name="threhold"></param>
  167. /// <returns></returns>
  168. public Rectangle GetRoiPos(Bitmap srcImage, Rectangle rcCrop, int offset, int threhold)
  169. {
  170. Rectangle newRoi = new(rcCrop.Location, rcCrop.Size);
  171. if (srcImage.PixelFormat != PixelFormat.Format24bppRgb)
  172. {
  173. return newRoi; // 暂时只处理24bit图像
  174. }
  175. BitmapData bmpData = srcImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  176. int vg1 = 0;//, vg2 = 0, vg3, vg4 = 0, vg5 = 0;
  177. int top = Math.Max(0, rcCrop.Top - offset);
  178. int bottom = Math.Min(srcImage.Height - 1, rcCrop.Bottom + offset);
  179. int left = Math.Max(0, (rcCrop.Left - offset));
  180. int right = Math.Min(srcImage.Width - 1, (rcCrop.Right + offset));
  181. unsafe
  182. {
  183. int pos = 0;
  184. // 上边界
  185. byte* pSrc = (byte*)(void*)bmpData.Scan0;
  186. for (int i = top; i <= bottom; i++)
  187. {
  188. for (int j = left; j <= right; j++)
  189. {
  190. pos = bmpData.Stride * i + j * 3 + 1;
  191. vg1 = *(pSrc + pos);
  192. if (vg1 >= threhold)
  193. {
  194. top = i; i = bottom + 1; // 找到边界,终止循环
  195. break;
  196. }
  197. }
  198. }
  199. // 下边界
  200. pSrc = (byte*)(void*)bmpData.Scan0;
  201. for (int i = bottom; i >= top; i--)
  202. {
  203. for (int j = left; j <= right; j++)
  204. {
  205. pos = bmpData.Stride * i + j * 3 + 1;
  206. vg1 = *(pSrc + pos);
  207. if (vg1 >= threhold)
  208. {
  209. bottom = i; i = top - 1; // 找到边界,终止循环
  210. break;
  211. }
  212. }
  213. }
  214. // 左边界
  215. pSrc = (byte*)(void*)bmpData.Scan0;
  216. for (int i = left; i <= right; i++)
  217. {
  218. for (int j = top; j <= bottom; j++)
  219. {
  220. pos = bmpData.Stride * j + i * 3 + 1;
  221. vg1 = *(pSrc + pos);
  222. if (vg1 >= threhold)
  223. {
  224. left = i; i = right + 1; // 找到边界,终止循环
  225. break;
  226. }
  227. }
  228. }
  229. // 右边界
  230. pSrc = (byte*)(void*)bmpData.Scan0;
  231. for (int i = right; i >= left; i--)
  232. {
  233. for (int j = top; j <= bottom; j++)
  234. {
  235. pos = bmpData.Stride * j + i * 3 + 1;
  236. vg1 = *(pSrc + pos);
  237. if (vg1 >= threhold)
  238. {
  239. right = i; i = left - 1; // 找到边界,终止循环
  240. break;
  241. }
  242. }
  243. }
  244. }
  245. srcImage.UnlockBits(bmpData);
  246. newRoi.X = ((left + right) - rcCrop.Width) / 2 + 1;
  247. newRoi.Y = ((top + bottom) - rcCrop.Height) / 2 + 1;
  248. //PublicDatas.LogProgram.Info(string.Format("found roi left={0}, right={1}, top = {2}, bottom = {3}", left, right, top, bottom));
  249. return newRoi;
  250. }
  251. /// <summary>
  252. /// 以图像最大值的1/2作为阈值,找到上下左右边界,然后以此为中心返回新的目标矩形区域
  253. /// </summary>
  254. /// <param name="srcImage"></param>
  255. /// <param name="rcCrop"></param>
  256. /// <param name="offset"></param>
  257. /// <returns></returns>
  258. public Rectangle GetRoiPos(Bitmap srcImage, Rectangle rcCrop, int offset)
  259. {
  260. Rectangle newRoi = new(rcCrop.Location, rcCrop.Size);
  261. if (srcImage.PixelFormat != PixelFormat.Format24bppRgb)
  262. {
  263. return newRoi; // 暂时只处理24bit图像
  264. }
  265. BitmapData bmpData = srcImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  266. int vg1 = 0;
  267. int top = Math.Max(0, rcCrop.Top - offset);
  268. int bottom = Math.Min(srcImage.Height - 1, rcCrop.Bottom + offset);
  269. int left = Math.Max(0, (rcCrop.Left - offset));
  270. int right = Math.Min(srcImage.Width - 1, (rcCrop.Right + offset));
  271. unsafe
  272. {
  273. int pos = 0;
  274. // 找出最大值的1/2作为阈值
  275. double threhold = 0;
  276. byte* pSrc = (byte*)(void*)bmpData.Scan0;
  277. for (int i = top; i <= bottom; i++)
  278. {
  279. for (int j = left; j <= right; j++)
  280. {
  281. pos = bmpData.Stride * i + j * 3 + 0;
  282. vg1 = *(pSrc + pos);
  283. if (vg1 >= threhold)
  284. {
  285. threhold = vg1;
  286. }
  287. }
  288. }
  289. if (threhold > 0) { threhold /= 2.0; }
  290. else { threhold = 10; }
  291. //PublicDatas.LogProgram.Debug("自动定位,定位阈值=" + threhold.ToString("F1"));
  292. // 上边界
  293. pSrc = (byte*)(void*)bmpData.Scan0;
  294. for (int i = top; i <= bottom; i++)
  295. {
  296. for (int j = left; j <= right; j++)
  297. {
  298. pos = bmpData.Stride * i + j * 3 + 0;
  299. vg1 = *(pSrc + pos);
  300. if (vg1 >= threhold)
  301. {
  302. top = i; i = bottom + 1; // 找到边界,终止循环
  303. break;
  304. }
  305. }
  306. }
  307. // 下边界
  308. pSrc = (byte*)(void*)bmpData.Scan0;
  309. for (int i = bottom; i >= top; i--)
  310. {
  311. for (int j = left; j <= right; j++)
  312. {
  313. pos = bmpData.Stride * i + j * 3 + 0;
  314. vg1 = *(pSrc + pos);
  315. if (vg1 >= threhold)
  316. {
  317. bottom = i; i = top - 1; // 找到边界,终止循环
  318. break;
  319. }
  320. }
  321. }
  322. // 左边界
  323. pSrc = (byte*)(void*)bmpData.Scan0;
  324. for (int i = left; i <= right; i++)
  325. {
  326. for (int j = top; j <= bottom; j++)
  327. {
  328. pos = bmpData.Stride * j + i * 3 + 0;
  329. vg1 = *(pSrc + pos);
  330. if (vg1 >= threhold)
  331. {
  332. left = i; i = right + 1; // 找到边界,终止循环
  333. break;
  334. }
  335. }
  336. }
  337. // 右边界
  338. pSrc = (byte*)(void*)bmpData.Scan0;
  339. for (int i = right; i >= left; i--)
  340. {
  341. for (int j = top; j <= bottom; j++)
  342. {
  343. pos = bmpData.Stride * j + i * 3 + 0;
  344. vg1 = *(pSrc + pos);
  345. if (vg1 >= threhold)
  346. {
  347. right = i; i = left - 1; // 找到边界,终止循环
  348. break;
  349. }
  350. }
  351. }
  352. }
  353. srcImage.UnlockBits(bmpData);
  354. newRoi.X = ((left + right) - rcCrop.Width) / 2 + 1;
  355. newRoi.Y = ((top + bottom) - rcCrop.Height) / 2 + 1;
  356. //PublicDatas.LogProgram.Info(string.Format("found roi left={0}, right={1}, top = {2}, bottom = {3}", left, right, top, bottom));
  357. return newRoi;
  358. }
  359. /// <summary>
  360. /// 在指定的矩形区域内查找大于阈值的像素点的坐标点
  361. /// </summary>
  362. /// <param name="srcImage">图像像素数据</param>
  363. /// <param name="rcCrop">指定矩形区域</param>
  364. /// <param name="threholdVal">G值的阈值</param>
  365. /// <returns>所有满足要求的坐标点</returns>
  366. public List<Point> GetRoiMask(Bitmap srcImage, Rectangle rcCrop, double threholdVal = 20)
  367. {
  368. List<Point> roiMask = new();
  369. if (srcImage.PixelFormat != PixelFormat.Format24bppRgb)
  370. {
  371. return null; // 暂时只处理24bit图像
  372. }
  373. BitmapData bmpData = srcImage.LockBits(rcCrop, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  374. int vb = 0; // 单个像素点 vg = 0, vr = 0,
  375. unsafe
  376. {
  377. byte* pSrc = (byte*)(void*)bmpData.Scan0;
  378. for (int i = 0; i < bmpData.Height; i++)
  379. {
  380. for (int j = 0; j < bmpData.Width; j++)
  381. {
  382. vb = *(pSrc + bmpData.Stride * i + j * 3 + 0); // 0
  383. //vg = *(pSrc + bmpData.Stride * i + j * 3 + 1); // 1
  384. //vr = *(pSrc + bmpData.Stride * i + j * 3 + 2); // 2
  385. if (vb >= threholdVal)
  386. {
  387. roiMask.Add(new Point(rcCrop.Left + j, rcCrop.Top + i));
  388. }
  389. }
  390. }
  391. }
  392. srcImage.UnlockBits(bmpData);
  393. return roiMask;
  394. }
  395. /// <summary>
  396. /// 统计指定图像区域的rgb总值
  397. /// </summary>
  398. /// <param name="srcImage"></param>
  399. /// <param name="rcCrop"></param>
  400. /// <param name="sumR"></param>
  401. /// <param name="sumG"></param>
  402. /// <param name="sumB"></param>
  403. /// <param name="noiseFilter">是否使用噪点过滤</param>
  404. /// <returns></returns>
  405. public bool GetTotalFromImage(Bitmap srcImage, Rectangle rcCrop, ref int sumR, ref int sumG, ref int sumB, NoiseDataFilter noiseFilter = null)
  406. {
  407. if (srcImage.PixelFormat != PixelFormat.Format24bppRgb)
  408. {
  409. return false; // 暂时只处理24bit图像
  410. }
  411. BitmapData bmpData = srcImage.LockBits(rcCrop, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
  412. sumR = sumG = sumB = 0; // 指定颜色总和
  413. int vr = 0, vg = 0, vb = 0; // 单个像素点
  414. unsafe
  415. {
  416. int logR = 0, logG = 0, logB = 0; // 统计原始数据的总值,用于写日志
  417. string strr = "R:\r\n";
  418. string strg = "G:\r\n";
  419. string strb = "B:\r\n";
  420. List<Color> img = new(); // 用于过滤的像素数据
  421. byte* pSrc = (byte*)(void*)bmpData.Scan0;
  422. for (int i = 0; i < bmpData.Height; i++)
  423. {
  424. for (int j = 0; j < bmpData.Width; j++)
  425. {
  426. vb = *(pSrc + bmpData.Stride * i + j * 3 + 0);
  427. vg = *(pSrc + bmpData.Stride * i + j * 3 + 1);
  428. vr = *(pSrc + bmpData.Stride * i + j * 3 + 2);
  429. logB += vb;
  430. logG += vg;
  431. logR += vr;
  432. if (noiseFilter == null)
  433. {
  434. sumB += vb;
  435. sumG += vg;
  436. sumR += vr;
  437. }
  438. else
  439. {
  440. img.Add(Color.FromArgb(vr, vg, vb));
  441. }
  442. if (IsLog)
  443. {
  444. strr = string.Format("{0}{1},", strr, vr.ToString().PadLeft(3, ' '));
  445. strg = string.Format("{0}{1},", strg, vg.ToString().PadLeft(3, ' '));
  446. strb = string.Format("{0}{1},", strb, vb.ToString().PadLeft(3, ' '));
  447. }
  448. }
  449. if (IsLog)
  450. {
  451. strr = string.Format("{0}\r\n", strr);
  452. strg = string.Format("{0}\r\n", strg);
  453. strb = string.Format("{0}\r\n", strb);
  454. }
  455. }
  456. #region 将rgb值写入日志
  457. if (this.IsLog)
  458. {
  459. try
  460. {
  461. string filename = @"d:\log\rgbdata_" + DateTime.Now.ToString("yyyyMMdd") + ".txt";
  462. filename = @"d:\log\rgbdata_" + DateTime.Now.ToString("yyyyMMdd") + ".txt";
  463. StreamWriter sw = new(filename, true, System.Text.Encoding.Default);
  464. sw.WriteLine(DateTime.Now.ToString("yyyyMMdd hh:mm:ss.fff") + " 原始数据:");
  465. //sw.WriteLine(strr);
  466. sw.WriteLine(strg);
  467. //sw.WriteLine(strb);
  468. sw.WriteLine();
  469. if (noiseFilter != null)
  470. {
  471. // 写日志
  472. noiseFilter.IsLog = true;
  473. noiseFilter.swLog = sw;
  474. noiseFilter.LogWidth = bmpData.Width;
  475. noiseFilter.CalcImage(img, ref sumR, ref sumG, ref sumB);
  476. }
  477. int tmp = bmpData.Width * bmpData.Height;
  478. strr = string.Format("原始总值:(R, G, B)({0}, {1}, {2}), 数据个数:{3}, ", logR, logG, logB, tmp)
  479. + string.Format("均值:(R, G, B)({0}, {1}, {2})\r\n", (logR * 1.0 / tmp).ToString("F2"), (logG * 1.0 / tmp).ToString("F2"), (logB * 1.0 / tmp).ToString("F2"));
  480. sw.WriteLine(strr);
  481. sw.WriteLine();
  482. sw.Close();
  483. }
  484. catch (Exception) { }
  485. }
  486. else
  487. {
  488. // 不用写日志
  489. noiseFilter?.CalcImage(img, ref sumR, ref sumG, ref sumB);
  490. }
  491. #endregion
  492. }
  493. srcImage.UnlockBits(bmpData);
  494. return true;
  495. }
  496. /// <summary>
  497. /// 根据指定点的坐标队列,计算总值
  498. /// </summary>
  499. /// <param name="srcImage"></param>
  500. /// <param name="roiPoint">计算点的坐标队列</param>
  501. /// <param name="sumR"></param>
  502. /// <param name="sumG"></param>
  503. /// <param name="sumB"></param>
  504. /// <param name="noiseFilter"></param>
  505. /// <returns></returns>
  506. public bool GetTotalFromImage(Bitmap srcImage, List<Point> roiPoint, ref int sumR, ref int sumG, ref int sumB, NoiseDataFilter noiseFilter = null)
  507. {
  508. if (srcImage.PixelFormat != PixelFormat.Format24bppRgb)
  509. {
  510. return false; // 暂时只处理24bit图像
  511. }
  512. BitmapData bmpData = srcImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  513. sumR = sumG = sumB = 0; // 指定颜色总和
  514. int vr = 0, vg = 0, vb = 0; // 单个像素点
  515. unsafe
  516. {
  517. int logR = 0, logG = 0, logB = 0; // 统计原始数据的总值,用于写日志
  518. //string strr = "R:\r\n";
  519. //string strg = "G:\r\n";
  520. //string strb = "B:\r\n";
  521. List<Color> img = new(); // 用于过滤的像素数据
  522. byte* pSrc = (byte*)(void*)bmpData.Scan0;
  523. foreach (Point pt in roiPoint)
  524. {
  525. vb = *(pSrc + bmpData.Stride * pt.Y + pt.X * 3 + 0);
  526. vg = *(pSrc + bmpData.Stride * pt.Y + pt.X * 3 + 1);
  527. vr = *(pSrc + bmpData.Stride * pt.Y + pt.X * 3 + 2);
  528. logB += vb;
  529. logG += vg;
  530. logR += vr;
  531. if (noiseFilter == null)
  532. {
  533. sumB += vb;
  534. sumG += vg;
  535. sumR += vr;
  536. }
  537. else
  538. {
  539. img.Add(Color.FromArgb(vr, vg, vb));
  540. }
  541. }
  542. #region 将rgb值写入日志
  543. /*if (IsLog)
  544. {
  545. try
  546. {
  547. string filename = @"d:\log\rgbdata_" + DateTime.Now.ToString("yyyyMMdd") + ".txt";
  548. filename = @"d:\log\rgbdata_" + DateTime.Now.ToString("yyyyMMdd") + ".txt";
  549. StreamWriter sw = new StreamWriter(filename, true, System.Text.Encoding.Default);
  550. sw.WriteLine(DateTime.Now.ToString("yyyyMMdd hh:mm:ss.fff") + " 原始数据:");
  551. sw.WriteLine(strr);
  552. sw.WriteLine(strg);
  553. sw.WriteLine(strb);
  554. sw.WriteLine();
  555. if (noiseFilter != null)
  556. {
  557. // 写日志
  558. noiseFilter.IsLog = true;
  559. noiseFilter.swLog = sw;
  560. noiseFilter.LogWidth = bmpData.Width;
  561. noiseFilter.CalcImage(img, ref sumR, ref sumG, ref sumB);
  562. }
  563. int tmp = bmpData.Width * bmpData.Height;
  564. strr = string.Format("原始总值:(R, G, B)({0}, {1}, {2}), 数据个数:{3}, ", logR, logG, logB, tmp)
  565. + string.Format("均值:(R, G, B)({0}, {1}, {2})\r\n", (logR * 1.0 / tmp).ToString("F2"), (logG * 1.0 / tmp).ToString("F2"), (logB * 1.0 / tmp).ToString("F2"));
  566. sw.WriteLine(strr);
  567. sw.WriteLine();
  568. sw.Close();
  569. }
  570. catch (Exception)
  571. {
  572. }
  573. }
  574. else
  575. {
  576. // 不用写日志
  577. if (noiseFilter != null)
  578. {
  579. noiseFilter.CalcImage(img, ref sumR, ref sumG, ref sumB);
  580. }
  581. }*/
  582. #endregion
  583. }
  584. srcImage.UnlockBits(bmpData);
  585. return true;
  586. }
  587. #endregion
  588. }
  589. }