ExposedIntent.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using OpenCvSharp;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace PaintDotNet.Adjust
  8. {
  9. /// <summary>
  10. /// 曝光处理
  11. /// </summary>
  12. public unsafe class ExposedIntent
  13. {
  14. private static int underExposedPixel = 0;//曝光不足像素阈值
  15. private static int overExposedPixel = 0;//过曝光像素阈值
  16. private static float ratio = 0;//占总像素点比例
  17. private static Mat exposedMat;//全局mat对象
  18. private static float underPixelCount = 0;//过暗像素点个数
  19. private static float overPixelCount = 0;//过亮像素点个数
  20. private static float allPixelCount = 0;//总像素点个数
  21. /// <summary>
  22. /// 判断曝光状态并返回对应像素点数量
  23. /// </summary>
  24. /// <param name="src"></param>
  25. /// <returns></returns>
  26. public static void ExposureState(Mat src)
  27. {
  28. //配置输出的结果存储的 空间 ,用MatND类型来存储结果
  29. Mat hist = new Mat();
  30. //设置计算的维度
  31. int dims = 1;
  32. //每一个维度的柱条的数目(就是将数值分组,共有多少组)
  33. int[] histSize = { 256 };
  34. Rangef[] pranges = new Rangef[1];//一个通道,范围
  35. pranges[0].Start = 0.0F;//从0开始(含)
  36. pranges[0].End = 256.0F;//到256结束(不含)
  37. Mat grayMat = src.CvtColor(ColorConversionCodes.BGRA2GRAY);//转换为灰度图
  38. //计算直方图
  39. Cv2.CalcHist(new Mat[1] { grayMat }, new int[] { 0 }, new Mat(), hist, dims, histSize, pranges);
  40. //循环记录像素点
  41. for (int i = 0; i < hist.Height; i++)
  42. {
  43. for (int j = 0; j < hist.Width; j++)
  44. {
  45. float pixelCount = hist.At<float>(i, j);
  46. allPixelCount += pixelCount;
  47. if (i < underExposedPixel && underExposedPixel != 0)
  48. underPixelCount += pixelCount;
  49. if (i > overExposedPixel && overExposedPixel != 0)
  50. overPixelCount += pixelCount;
  51. }
  52. }
  53. }
  54. /// <summary>
  55. /// 曝光不足,替换像素点为蓝色
  56. /// </summary>
  57. /// <param name="src"></param>
  58. /// <param name="underExposedPixel">曝光不足像素阈值</param>
  59. /// <param name="ratio">占总像素点比例</param>
  60. /// <returns></returns>
  61. public static Mat UnderExposed(Mat src, int thresholdvalue, float exposedRatio)
  62. {
  63. underExposedPixel = thresholdvalue;
  64. ratio = exposedRatio;
  65. exposedMat = src;
  66. ExposureState(src);
  67. //判断过暗,如果阈值内的像素点多余总像素点一定比例
  68. if (underPixelCount > 0)
  69. {
  70. if (underPixelCount / allPixelCount > ratio)
  71. {
  72. Mat grayMat = src.CvtColor(ColorConversionCodes.BGRA2GRAY);//转换为灰度图
  73. grayMat.ForEachAsByte(ForeachFunctionUnderExposedByte);
  74. }
  75. }
  76. return exposedMat;
  77. }
  78. /// <summary>
  79. /// 过曝光,替换像素点为红色
  80. /// </summary>
  81. /// <param name="src"></param>
  82. /// <param name="overExposedPixel">过曝光像素阈值</param>
  83. /// <param name="ratio">占总像素点比例</param>
  84. /// <returns></returns>
  85. public static Mat OverExposed(Mat src, int thresholdvalue, float exposedRatio)
  86. {
  87. overExposedPixel = thresholdvalue;
  88. ratio = exposedRatio;
  89. exposedMat = src;
  90. ExposureState(src);
  91. //判断过亮,如果阈值内的像素点多余总像素点一定比例
  92. if (overPixelCount > 0)
  93. {
  94. if (overPixelCount / allPixelCount > ratio)
  95. {
  96. Mat grayMat = src.CvtColor(ColorConversionCodes.BGRA2GRAY);//转换为灰度图
  97. grayMat.ForEachAsByte(ForeachFunctionOverExposedByte);
  98. }
  99. }
  100. return exposedMat;
  101. }
  102. /// <summary>
  103. /// 更高效的循环替换方法-曝光不足
  104. /// </summary>
  105. /// <param name="t"></param>
  106. /// <param name="position"></param>
  107. public unsafe static void ForeachFunctionUnderExposedByte(byte* t, int* position)
  108. {
  109. int y = position[0];
  110. int x = position[1];
  111. if (*t < underExposedPixel)
  112. {
  113. exposedMat.Set<Vec3b>(y, x, new Vec3b(255, 0, 0));//改为蓝色
  114. }
  115. }
  116. /// <summary>
  117. /// 更高效的循环替换方法-过曝光
  118. /// </summary>
  119. /// <param name="t"></param>
  120. /// <param name="position"></param>
  121. public unsafe static void ForeachFunctionOverExposedByte(byte* t, int* position)
  122. {
  123. int y = position[0];
  124. int x = position[1];
  125. if (*t > overExposedPixel)
  126. {
  127. exposedMat.Set<Vec3b>(y, x, new Vec3b(0, 0, 255));//改为红色
  128. }
  129. }
  130. }
  131. }