这里主要使用CImg图像库
算法解析
算法主要参考了论文 “Adaptive Thresholding Using the Integral Image” 中的实现方式(CSDN下载要积分,需要的可以直接留言)
算法代码
CImg<double> AdaptiveThreshold(CImg<double>& src, int thres = 20) {
// 生成等大新图像并初始化
CImg<double> temp = CImg<double>(src.width(), src.height(), 1, 1);
// 转为灰度图
CImg<double> grey_img = RGB2Gray(src);
CImg<double> result = grey_img;
temp.fill(0);
result.fill(0);
double sum = 0, t = thres;
int windowsize = 100;
// 这段可以理解为将图像以左上角点与图像上任意一点连线作为对角线的矩形图像区域的像素值的和
// 用于加速运算
for(int x = 0; x < grey_img.width(); x++) {
sum = 0;
for(int y = 0; y < grey_img.height(); y++) {
sum = sum + grey_img(x,y);
if(x == 0) {
temp(x,y) = sum;
}
else{
temp(x,y) = temp(x-1,y) + sum;
}
}
}
// 寻找动态阈值
for(int i = 0; i < grey_img.width(); i++){
for(int j = 0; j < grey_img.height(); j++) {
int x1 = i - windowsize / 2;
int x2 = i + windowsize / 2;
int y1 = j - windowsize / 2;
int y2 = j + windowsize / 2;
if(x1 < 1){
x1 = 1;
}
if(y1 < 1){
y1 = 1;
}
if(x2 >= grey_img.width()){
x2 = grey_img.width()-1;
}
if(y2 >= grey_img.height()){
y2 = grey_img.height()-1;
}
int count = (x2-x1)*(y2-y1);
// 矩形图像区域的像素值的和
sum = temp(x2,y2) - temp(x2, y1-1) - temp(x1-1,y2) + temp(x1-1, y1-1);
// 二值化
if(grey_img(i,j) * count <= sum * (100-t)/100.0f ){
result(i,j) = 255;
}
else{
result(i,j) = 0;
}
}
}
// 结果
this->AdaptLineImg = result;
return result;
}