using OpenCvSharp; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PaintDotNet.Adjust { /// /// 曝光处理 /// public unsafe class ExposedIntent { private static int underExposedPixel = 0;//曝光不足像素阈值 private static int overExposedPixel = 0;//过曝光像素阈值 private static float ratio = 0;//占总像素点比例 private static Mat exposedMat;//全局mat对象 private static float underPixelCount = 0;//过暗像素点个数 private static float overPixelCount = 0;//过亮像素点个数 private static float allPixelCount = 0;//总像素点个数 /// /// 判断曝光状态并返回对应像素点数量 /// /// /// public static void ExposureState(Mat src) { //配置输出的结果存储的 空间 ,用MatND类型来存储结果 Mat hist = new Mat(); //设置计算的维度 int dims = 1; //每一个维度的柱条的数目(就是将数值分组,共有多少组) int[] histSize = { 256 }; Rangef[] pranges = new Rangef[1];//一个通道,范围 pranges[0] = new Rangef(0.0F, 256.0F); Mat grayMat = src.CvtColor(ColorConversionCodes.BGRA2GRAY);//转换为灰度图 //计算直方图 Cv2.CalcHist(new Mat[1] { grayMat }, new int[] { 0 }, new Mat(), hist, dims, histSize, pranges); //循环记录像素点 for (int i = 0; i < hist.Height; i++) { for (int j = 0; j < hist.Width; j++) { float pixelCount = hist.At(i, j); allPixelCount += pixelCount; if (i < underExposedPixel && underExposedPixel != 0) underPixelCount += pixelCount; if (i > overExposedPixel && overExposedPixel != 0) overPixelCount += pixelCount; } } } /// /// 曝光不足,替换像素点为蓝色 /// /// /// 曝光不足像素阈值 /// 占总像素点比例 /// public static Mat UnderExposed(Mat src, int thresholdvalue, float exposedRatio) { underExposedPixel = thresholdvalue; ratio = exposedRatio; exposedMat = src; ExposureState(src); //判断过暗,如果阈值内的像素点多余总像素点一定比例 if (underPixelCount > 0) { if (underPixelCount / allPixelCount > ratio) { Mat grayMat = src.CvtColor(ColorConversionCodes.BGRA2GRAY);//转换为灰度图 grayMat.ForEachAsByte(ForeachFunctionUnderExposedByte); } } return exposedMat; } /// /// 过曝光,替换像素点为红色 /// /// /// 过曝光像素阈值 /// 占总像素点比例 /// public static Mat OverExposed(Mat src, int thresholdvalue, float exposedRatio) { overExposedPixel = thresholdvalue; ratio = exposedRatio; exposedMat = src; ExposureState(src); //判断过亮,如果阈值内的像素点多余总像素点一定比例 if (overPixelCount > 0) { if (overPixelCount / allPixelCount > ratio) { Mat grayMat = src.CvtColor(ColorConversionCodes.BGRA2GRAY);//转换为灰度图 grayMat.ForEachAsByte(ForeachFunctionOverExposedByte); } } return exposedMat; } /// /// 更高效的循环替换方法-曝光不足 /// /// /// public unsafe static void ForeachFunctionUnderExposedByte(byte* t, int* position) { int y = position[0]; int x = position[1]; if (*t < underExposedPixel) { exposedMat.Set(y, x, new Vec3b(255, 0, 0));//改为蓝色 } } /// /// 更高效的循环替换方法-过曝光 /// /// /// public unsafe static void ForeachFunctionOverExposedByte(byte* t, int* position) { int y = position[0]; int x = position[1]; if (*t > overExposedPixel) { exposedMat.Set(y, x, new Vec3b(0, 0, 255));//改为红色 } } } }