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));//改为红色
}
}
}
}