本系列文章由@邻居张师傅 出品,转载请注明出处。
文章链接: https://editor.csdn.net/md?articleId=106491750
邮箱: zhangyh_nb@163.com
当前使用OpenCV版本: 4.0.1
目录
- 原理
- 实现
- 参考
原理 相比于对整幅图像取一个固定的阈值,由于光照不均匀等原因,跟一般的方法是对一幅图像中的每个像素点计算阈值,即可变局部阈值。
算法表示如下:
m ( k + 1 ) = 1 n ∑ i = k + 2 ? n k + 1 z i ( 1.1 ) m(k+1)=\frac{1}{n}\sum^{k+1}_{i=k+2-n}z_{i}(1.1) m(k+1)=n1?i=k+2?n∑k+1?zi?(1.1)
其中,z k + 1 z_{k+1} zk+1?表示在扫描序列中第 k + 1 k+1 k+1步遇到的点的灰度值, m ( k ) m(k) m(k)为输入图像的第 k k k个点的像素值, n n n表示用于计算平均的点的数量。
根据(1.1)有下式:
m ( k ) = 1 n ∑ i = k + 1 ? n k z i ( 1.2 ) m(k)=\frac{1}{n}\sum^{k}_{i=k+1-n}z_{i}(1.2) m(k)=n1?i=k+1?n∑k?zi?(1.2)
根据(1.1)、(1.2)不难得出下式子:
m ( k + 1 ) = 1 n ∑ i = k + 2 ? n k + 1 z i = m ( k ) + 1 n ( z k + 1 ? z k + 1 ? n ) ( 1.3 ) m(k+1)=\frac{1}{n}\sum^{k+1}_{i=k+2-n}z_{i}=m(k)+\frac{1}{n}(z_{k+1}-z_{k+1-n})(1.3) m(k+1)=n1?i=k+2?n∑k+1?zi?=m(k)+n1?(zk+1??zk+1?n?)(1.3)
接下来就根据每个点的阈值进行二值化操作。
注:我们仅仅在扫描的点的数量大于n时应用式(1.3),其他情况则将 z k + 1 ? n z_{k+1-n} zk+1?n?视为0,即相当于在图像的边界填充了n-1个0。
实现 以下是实现结果,左边是原图,右边是结果。
文章图片
下面是代码:
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include
#include using namespace std;
using namespace cv;
void movingThreshold(const Mat &src,Mat &dst,int n=20,float b=0.75);
int main(){
Mat src=https://www.it610.com/article/imread("1.tif",IMREAD_GRAYSCALE);
namedWindow("src",WINDOW_NORMAL);
imshow("src",src);
Mat dst;
movingThreshold(src,dst);
namedWindow("dst",WINDOW_NORMAL);
imshow("dst",dst);
waitKey();
}void movingThreshold(const Mat &src,Mat &dst,int n,float b){int arrayNum=src.rows*src.cols;
uchar *temp = new uchar[arrayNum];
for(int y=0;
y.rows;
y++){//二维转换为一维Z字扫描
for(int x=0;
x.cols;
x++){
if(y%2==0)
temp[y*src.rows+x]=src.at(y,x);
else
temp[y*src.rows+x]=src.at(y,src.cols-1-x);
}
}dst.create(src.size(),CV_8U);
float m_now=0,m_pre=0,dif=0;
int index=0;
for(int y=0;
y.rows;
y++)
for(int x=0;
x.cols;
x++){
index=y*src.rows+x;
if(index+1(y,x)>b*m_now)
dst.at(y,x)=255;
else
dst.at(y,x)=0;
}
delete [] temp;
}
参考 【Opencv|移动平均的阈值处理 opencv实现】1.冈萨雷斯. 数字图像处理[M]. 北京: 电子工业出版社, 2005.
推荐阅读
- 人脸识别|【人脸识别系列】| 实现自动化妆
- OpenCV|OpenCV-Python实战(18)——深度学习简介与入门示例
- 个人日记|K8s中Pod生命周期和重启策略
- 学习分享|【C语言函数基础】
- opencv|图像处理之椒盐噪声的添加与去除
- 人脸识别|【人脸识别系列】| 实现人脸截图保存并编写128维特征向量
- C++|C++浇水装置问题
- 数据结构|C++技巧(用class类实现链表)
- opencv|网络爬虫入门练习
- C++|从零开始学C++之基本知识