【发布时间】:2013-12-11 21:32:56
【问题描述】:
我想问一些与二值化相关的想法/学习材料。我正在尝试创建检测人类情绪的系统。我能够获得眉毛、眼睛、鼻子、嘴巴等区域,但随后进入另一个阶段 -> 处理......
我的照片是在不同的地方/一天中的时间/天气条件下拍摄的。在二值化过程中存在问题,具有相同的阈值,一张图像是全黑的,其他看起来很好,并为我提供了我想要的信息。
我想问你的是:
1)如果有已知的方法如何使所有图像达到相同的亮度水平?
2) 如何在图像上创建阈值和亮度之间的依赖关系?
我现在尝试的是标准化图像......但没有效果,也许我做错了什么。我正在使用 OpenCV(适用于 android)
Core.normalize(cleanFaceMatGRAY, cleanFaceMatGRAY,0, 255, Core.NORM_MINMAX, CvType.CV_8U);
编辑:
我尝试了自适应阈值,OTSU - 它们对我不起作用。我在 Android 中使用 CLAHE 时遇到问题,但我设法实现了 Niblack 算法。
Core.normalize(cleanFaceMatGRAY, cleanFaceMatGRAY,0, 255, Core.NORM_MINMAX, CvType.CV_8U);
nibelBlackTresholding(cleanFaceMatGRAY, -0.2);
private void nibelBlackTresholding(Mat image, double parameter) {
Mat meanPowered = image.clone();
Core.multiply(image, image, meanPowered);
Scalar mean = Core.mean(image);
Scalar stdmean = Core.mean(meanPowered);
double tresholdValue = mean.val[0] + parameter * stdmean.val[0];
int totalRows = image.rows();
int totalCols = image.cols();
for (int cols=0; cols < totalCols; cols++) {
for (int rows=0; rows < totalRows; rows++) {
if (image.get(rows, cols)[0] > tresholdValue) {
image.put(rows, cols, 255);
} else {
image.put(rows, cols, 0);
}
}
}
}
结果非常好,但对于某些图像仍然不够。我粘贴链接,因为图像很大,我不想占用太多屏幕:
例如,这个非常好:
https://dl.dropboxusercontent.com/u/108321090/a1.png
https://dl.dropboxusercontent.com/u/108321090/a.png
但光线不好有时会产生阴影,这会产生以下效果: https://dl.dropboxusercontent.com/u/108321090/b1.png https://dl.dropboxusercontent.com/u/108321090/b.png
您有什么想法可以帮助我提高那些具有高光差(阴影)的图像的阈值吗?
编辑2:
我发现我以前的算法以错误的方式实现。 Std 的计算方式错误。在 Niblack Thresholding 中,平均值是局部值而不是全局值。我按照这个参考修复了http://arxiv.org/ftp/arxiv/papers/1201/1201.5227.pdf
private void niblackThresholding2(Mat image, double parameter, int window) {
int totalRows = image.rows();
int totalCols = image.cols();
int offset = (window-1)/2;
double tresholdValue = 0;
double localMean = 0;
double meanDeviation = 0;
for (int y=offset+1; y<totalCols-offset; y++) {
for (int x=offset+1; x<totalRows-offset; x++) {
localMean = calculateLocalMean(x, y, image, window);
meanDeviation = image.get(y, x)[0] - localMean;
tresholdValue = localMean*(1 + parameter * ( (meanDeviation/(1 - meanDeviation)) - 1 ));
Log.d("QWERTY","TRESHOLD " +tresholdValue);
if (image.get(y, x)[0] > tresholdValue) {
image.put(y, x, 255);
} else {
image.put(y, x, 0);
}
}
}
}
private double calculateLocalMean(int x, int y, Mat image, int window) {
int offset = (window-1)/2;
Mat tempMat;
Rect tempRect = new Rect();
Point leftTop, bottomRight;
leftTop = new Point(x - (offset + 1), y - (offset + 1));
bottomRight = new Point(x + offset, y + offset);
tempRect = new Rect(leftTop, bottomRight);
tempMat = new Mat(image, tempRect);
return Core.mean(tempMat).val[0];
}
7x7 窗口的结果并在参考 k 参数 = 0.34 中提出:我仍然无法摆脱脸上的阴影。
https://dl.dropboxusercontent.com/u/108321090/b2.png
https://dl.dropboxusercontent.com/u/108321090/b1.png
【问题讨论】:
标签: android opencv image-processing signal-processing