二值化每次都要调阈值,很头疼,实现一个不依赖OpenCV库的动态二值化算法很有必要。
测试了
参考文献
论文链接
更详细的算法解释
效果如下:
达到了预期的效果。
主要实现代码记录一下。
void MainWindow::BalancedThresholding()
{
QImage pos = img;
QRgb *bin = (QRgb *)pos.scanLine(0);
QRgb *pixels = (QRgb *)img.scanLine(0);
QRgb threadw = qRgb(255,255,255);
QRgb threadb = qRgb(0,0,0);
int w = img.width();
int h = img.height();
int index = 0;
int count = 0;
long sum = 0;
int x1,x2,y1,y2;
int S = w/8.0;
int s2 = S/2;
double T = 0.15;
unsigned long* integralImg = 0;
integralImg = (unsigned long*)malloc(w*h*sizeof(unsigned long*));
for(int i =0;i<w;i++)
{
sum = 0;
for(int j=0;j<h;j++)
{
index = j*w+i;
sum += qGray(pixels[index]);
if(i==0)
integralImg[index] = sum;
else
integralImg[index] = integralImg[index-1] + sum;
}
}
for(int i =0;i<w;i++)
{
sum = 0;
for(int j=0;j<h;j++)
{
index = j*w+i;
x1 = i-s2;
x2 = i+s2;
y1 = j-s2;
y2 = j+s2;
if(x1<0)x1=0;
if(x2>=w) x2=w-1;
if(y1<0) y1=0;
if(y2>=h) y2 = h-1;
count = (x2-x1)*(y2-y1);
sum = integralImg[y2*w+x2] - integralImg[y1*w+x2] - integralImg[y2*w +x1] + integralImg[y1*w+x1];
if((long)(qGray(pixels[index])*count) < (long)(sum*(1.0-T)))
{
bin[index] = threadb;
}
else
{
bin[index] = threadw;
}
}
}
free (integralImg);
ui->labelDest->setPixmap(QPixmap::fromImage(pos));
}
这里使用了自己熟悉的Qt,如果需要跨平台,可以使用stb_img库来读写图片,可以摆脱各种大框架的捆绑。