[英]Is there any way to detect image is Blurry after capturing from Camera in Android (Except OpenCV )
我正在使用 Camera2 API 并想检测捕获的图像是否模糊或清晰,为此我使用了 OpenCV,但结果并不令人满意,并且将 APK 大小增加了 3 倍,那么有什么方法可以检测模糊吗?
测量图像焦点/模糊涉及迭代位图的像素或其至少一部分。
虽然您不需要 OpenCV 在 Android 上迭代位图的像素,但它不适合胆小的人。 以一种高性能的方式执行此操作将需要您使用 JNI 本机代码,或者可能使用 RenderScript 之类的技术,因为在 Java 或 Kotlin 中迭代像素可能会太慢。
有许多算法和技术可用于测量焦距、锐度或对比度,这是我使用的一种并取得了相当成功的方法。
Luma 是像素的亮度,即灰度像素值。 您需要将每个像素转换为此焦点度量的灰度值。 例如使用 NTSC 公式:
pixelLuma = (red * 0.299) + (green * 0.587) + (blue * 0.114)
以下是衡量焦点得分的建议公式:
FocusScore = Max({Video_Gradient}) / {Gray_Level_Dynamic_Range} * {Pixel_Pitch}
Max{Video_Gradient} = 位图中相邻像素 (x,y) 之间最大亮度差异的度量。
例如:
水平测量pixel[x] - pixel[x+1]
垂直测量pixel[y] - pixel[y+1]
{Gray_Level_Dynamic_Range} = 位图中 N 个最亮像素和 N 个最暗像素的平均值之间的差异。 N 的典型值为 64,在我的情况下,处理大约 1200w x 500h 的图像。 较小的图像应该使用较小的 N。
{Pixel_Pitch} = 1 / DPI = 1/200 = 0.005
这将导致得分,更高的值更受关注。 您可以确定一个合理的阈值。
这是用 C 编写的代码片段:
- 宽度 = 位图的宽度
- 高度 = 位图的高度
- 像素 = 大小为(宽 * 高)的字节数组,用于保存像素亮度值
- VFOCUS_N = 64
int gradientHorizontal[256];
int *pGradientHorizontal = gradientHorizontal;
int gradientVertical[256];
int *pGradientVertical = gradientVertical;
int luminanceHistogram[256];
int *pLuminance = luminanceHistogram;
int maxGradient = 0;
for (int i = 0;i < 256;i++)
{
gradientHorizontal[i] = 0;
gradientVertical[i] = 0;
luminanceHistogram[i] = 0;
}
// pixel by pixel math...
for (nRow = 0; nRow < height-1; nRow++)
{
nRowOffset = nRow * width;
nNextRowOffset = (nRow+1) * width;
for (nCol = 0; nCol < width-1; nCol++)
{
int gC = pixels[nRowOffset + nCol];
int gH = abs(gC - pixels[nRowOffset + nCol + 1]);
int gV = abs(gC - pixels[nNextRowOffset + nCol]);
pLuminance[gC]++;
pGradientHorizontal[gH]++;
pGradientVertical[gV]++;
}
}
// find max gradient
for (int i = 255;i >= 0;i--)
{
// first one with a value
if ((gradientHorizontal[i] > 0) || (gradientVertical[i] > 0))
{
maxGradient = i;
break;
}
}
// calculate dynamic range
int rangeLow = 0;
int rangeHi = 0;
int p;
p = 0;
for (int i = 0;i < 256;i++)
{
if (luminanceHistogram[i] > 0)
{
if (p + luminanceHistogram[i] > VFOCUS_N)
{
rangeLow += (i * (VFOCUS_N - p));
p = VFOCUS_N;
break;
}
p += luminanceHistogram[i];
rangeLow += (i * luminanceHistogram[i]);
}
}
if (p)
rangeLow /= p;
p = 0;
for (int i = 255;i >= 0;i--)
{
if (luminanceHistogram[i] > 0)
{
if (p + luminanceHistogram[i] > VFOCUS_N)
{
rangeHi += (i * (VFOCUS_N - p));
p = VFOCUS_N;
break;
}
p += luminanceHistogram[i];
rangeHi += (i * luminanceHistogram[i]);
}
}
if (p)
rangeHi /= p;
float mFocusScore = (float)fmin((float)maxGradient / (fabs((float)rangeHi - (float)rangeLow) * 0.005), 100.00);
低对焦分数意味着图像模糊。 接近或超过 100 的值表示图像清晰,上面的代码将分数上限为 100。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.