1.原理
最简单的阈值分割即为手动设置阈值对图像进行二值化,大于设定的阈值像素值设置为255,小于设定阈值则为0.这种方法一般称为全局阈值分割,接下来想介绍的是一种局部阈值分割算法,其原理很简单,通俗地讲就是图片的每个局部都会通过处理得到一个阈值,这个区域就用这个阈值来进行分割,同理,每个区域都有不同的阈值来处理,如何来获取这个阈值就是整个算法的关键。
这里用opencv的API接口来进行说明,opencv库有接口函数
void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
src为输入图像,
dst为输出图像,
maxValue为设定的像素最大值,
adptiveMethod为使用的滤波方法,opencv给出了两种方法,分别为ADAPTIVE_THRESH_MEAN_C 和ADAPTIVE_THRESH_GAUSSIAN_C,
thresholdType为阈值类型,THRESH_BINARY 和THRESH_BINARY_INV,
blockSize指的是邻域的大小,也就是通常说的核的大小,一般为奇数,
C为阈值的偏移量。
当使用ADAPTIVE_THRESH_MEAN_C方法时阈值为邻域的均值减去C,当使用ADAPTIVE_THRESH_GAUSSIAN_C方法时,阈值为邻域的高斯均值减去C。
2.代码展示
自己的自适应阈值分割方法,加入了中值滤波
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
enum FliterMethod {
meanFliter,
gaaussianFliter,
medianFliter
};
void AdaptiveThreshold(Mat &src, Mat &dst,double Maxval, int Subsize,double C ,FliterMethod method )
{
if (src.channels() > 1)
cvtColor(src,src,CV_RGB2GRAY);
Mat smooth;
switch (method)
{
case meanFliter:
blur(src, smooth, Size(Subsize, Subsize));
break;
case gaaussianFliter:
GaussianBlur(src, smooth, Size(Subsize, Subsize), 0, 0);
break;
case medianFliter:
medianBlur(src, smooth, Subsize);
break;
default:
break;
}
smooth = smooth - C;
src.copyTo(dst);
int r = dst.rows;
int c = dst.cols;
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
if (dst.at<uchar>(i,j) > smooth.at<uchar>(i,j))
dst.at<uchar>(i,j) = Maxval;
else
dst.at<uchar>(i,j) = 0;
}
}
}
为了看下实时处理的效果,调用了电脑摄像头,代码如下
int Capture() {
VideoCapture cap;
cap.open(0);
Mat frame;
//Mat src;
if (!cap.isOpened())
return -1;
while (1)
{
cap.read(frame);
if (frame.empty())
break;
//GaussianBlur(frame, src, Size(5, 5), 3, 3);
Mat src,tmp;
AdaptiveThreshold(frame, src, 255, 7, 5, meanFliter);
adaptiveThreshold(frame, tmp, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 7, 10);
//imshow(" ", frame);
imshow("AdaptiveThreshold",src);
imshow("opencv", tmp);
waitKey(10);
}
cap.release();
destroyAllWindows();
}
以下为测试代码
int main()
{
Mat img = imread("C:/Users/94077/Desktop/QQ截图20200307162029.bmp");
Mat src,tmp;
AdaptiveThreshold(img, src, 255, 7, 10, gaaussianFliter);
adaptiveThreshold(img, tmp, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY,7, 10);
imshow("function", src);
imshow("opencv", tmp);
waitKey(0);
//Capture();
return 0;
}
3.结果展示
这里放几张处理的图片对比一下,发现还是opencv的库函数处理效果好一点,但是针对不同的图片,在某些时候中值滤波的效果可能要比其余两种效果好。