精华内容
下载资源
问答
  • 不均匀光照下车牌图像二值化研究不均匀光照下车牌图像二值化研究
  • 一种光照不均匀图像二值化方法
  • 基于光照不均匀图像的自适应二值化方法研究,可以针对光照均匀的图像进行处理。
  • 不均匀光照文本图像二值化

    万次阅读 多人点赞 2015-08-18 17:44:35
    因为文本图像的背景是不均匀的,所以想先求出图片的背景,再用原图减去背景,就会得出文本的内容,再进行二值化,就是我们想要的结果。 以下是详细的思路: 首先要估算出原始图片的背景图。 Is(x,y)点的背景...

    不均匀光照文本图像的二值化。

    因为文本图像的背景是不均匀的,所以想先求出图片的亮度背景,用原图减去背景,就会得出文本的内容,再进行二值化,可能就会得到我们想要的结果。


    以下是详细的处理过程:

    首先要估算出原始图片的背景图。

    图片中某一点的背景,可以用该点w*w邻域内较亮的点的集合来进行估算。就好比一张白纸,一个区域内最白的一些点就可以代表该区域的背景。

    我们逐行逐列的扫描图像,依次选取每个像素点w*w邻域内亮度最高的六个点。为了减少白噪声像点对背景的影响,我们去掉这六个点中最大的,对其余的五个点求平均值,认为这个平均值就是该点的背景值。

    以下为matlab实现:

    I = imread('C:\test.bmp');
    I = rgb2gray(I);
    %colfilt(I,[31 31],'sliding',@bk)
    % 功能:以列方法进行邻域处理,也可执行常规非线性滤波。
    % 用法:B = colfilt(A,[m n],block_type,fun)
    % 该函数生成了一幅图像A,在A中,每一列对应于其中心位于图像内某个位置的邻域所包围的像素。然后将函数应用于该矩阵中。
    % [m n]表示大小为m行n列的邻域。block_type表示了一个字符串,包括'distinct','sliding'两种,
    % 其中'sliding'是在输入图像中逐个像素地滑动该m乘n的区域。fun表示引用了一个函数进行处理,
    % 函数返回值的大小必须和原图像大小相同。
    I2 = uint8(colfilt(I,[31 31],'sliding',@bk));
    function v=bk(x)
        N = size(x);                    
        b = sort(x);
        nMax = b((N(1)-47) : (N(1)-1),:);
        v = mean(nMax);
    end
     

    原图以及求出的背景图
         

    想要去掉不均匀的光照背景,可以简单理解为,原图减去背景图。

    但是,可想而知,背景区域颜色越深的话,该区域背景与所要显示的文本之间的对比度就会越小。

    所以,要根据背景颜色的深浅,来对对比度进行补偿。


    k的值为连续分段的线性函数,其物理意义是对比度放大的倍数。

    可以简单理解为,背景颜色越深,k值越大。也就是背景颜色值越小,k值越大,对比度所需要放大的倍数越大。



    matlab实现如下:

    % 对背景暗区与背景亮区的对比度进行补偿
    I3 = minusBk(I,I2);
    function v=minusBk(A,B)
        F = 255;
        ret = A;
        [m,n] = size(A);
        for i=1 : m
            for j=1 : n
                k = setK(B(i,j));
                if B(i,j) > A(i,j)
                    ret(i,j) = F - k*(B(i,j)-A(i,j));
                    if ret(i,j) < 0.75*F
                        ret(i,j) = 0.75*F;
                    end
                else
                    ret(i,j) = F;
                end
            end
        end
        v=ret;
    end
    
    % get k
    function v=setK(e)
    if e < 20
        k = 2.5;
    elseif e>=20 && e<=100
        k = 1 + ((2.5-1)*(100-e))/80;
    elseif e>100 && e<200
        k = 1;
    else
        k = 1 + (e-220)/35;
    end
    v = k;
    end


    对比度补偿之后的结果




    对比度补偿之后,要对图片进行二值化。
    我们常见的图像二值化算法大致可分为全局阈值方法与局部阈值方法这两种类型。其中OTSU算法是全局阈值的代表,而Sauvola算法则是局部阈值方法的标杆。Sauvola算法的输入是灰度图像,它以当前像素点为中心,根据当前像素点邻域内的灰度均值与标准方差来动态计算该像素点的阈值。
    假定当前像素点的坐标为(x,y),以该点为中心的领域为r*r,g(x,y)表示(x,y)处的灰度值,Sauvola算法的步骤为:


    matlab实现Sauvola二值化:

    I4 = uint8(colfilt(I3,[31 31],'sliding',@sauvola));
    function v=sauvola(x)
    Y=128;
    m1= mean(x);                                                        
    v2 = double(x(481,:));
    s = size(v2);
    s1=(1-0.15*(1-std(double(x))/Y));
    v3=v2;
    for i = 1:s(2)
        if (v2(1,i)>m1(1,i)*s1(1,i))
           v3(1,i)=255;             
        else
           v3(1,i)=0;
        end
    end
    v = v3;
    end


    二值化的结果如下~


    实验结果还算满意。但是有的文本部分显示的还是不好,感觉是由于邻域的选取问题,邻域选的小,该邻域内笔画过多,导致邻域内的亮度平均值过低,低于实际的背景。从而导致的二值化结果异常。

    调大了二值化时选取的邻域,解决了上面的问题,但是对图像边缘部分的二值化,还是处理的有问题




    参考文献:

    ①不均匀光照文本图像的二值化 贺志明

    ②基于光照不均匀图像的自适应二值化方法研究 郭佳

    展开全文
  • 不均匀光照下的图像二值化是数字图像处理中的一个难题,汽车牌照自动识别系统工作在复杂的光照环境下,经常会出现车牌光照不均的现象,给图像二值化带来困难。为此,提出一种解决办法,首先使用同态滤波去掉车牌图像...
  • 利用sauvola实现图像二值化,很好的解决了光照不均匀产生的影响,这是我用c++实现后编译成mexw32 文件,方便matlab调用。适用于32位window系统
  • 图像处理:图像二值化原理

    千次阅读 多人点赞 2019-06-18 16:44:54
    在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样...

    图像的二值化的基本原理

    图像的二值化处理就是讲图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的阀值选取而获得仍然可以反映图像整体和局部特征的二值化图像。在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样子有利于再对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单,而且数据的处理和压缩量小。为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。所有灰度大于或等于阀值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用阀值法就可以得到比较的分割效果。如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阀值选取技术来分割该图像。动态调节阀值实现图像的二值化可动态观察其分割图像的具体结果。
    --------------------- 
     

    展开全文
  • 图像二值化

    千次阅读 2017-05-24 20:23:40
    二值化广泛应用于图像分割、图像增强、... 阈值的选取是图像二值化的关键问题。在灰度图像中,由于物体与背景的灰度分布存在着一定的差别,把整幅灰度图像用灰度直方图表示,则图中必然存在波峰和波谷。最简单的情况

            二值化广泛应用于图像分割、图像增强、图像识别等领域。二值图像具有存储空间小、处理速度快等特点,可以方便进行布尔逻辑运算,可以比较容易获取目标区域的几何特征或者其他特征,比如描述目标区域的边界、获取目标区域的位置和大小等。

            阈值的选取是图像二值化的关键问题。在灰度图像中,由于物体与背景的灰度分布存在着一定的差别,把整幅灰度图像用灰度直方图表示,则图中必然存在波峰和波谷。最简单的情况是存在两个峰值的情况,通常选取波谷位置即可得到较佳的阈值。但是,实际图像处理的过程,图像的灰度直方图往往比两个峰值的情况更复杂,目标内部的灰度分布也不均匀,而且由于噪声的影响使图像产生多个峰值,目标的灰度和背景相差不明显,使灰度直方图出现单峰值的情况。在这些情况下,阈值的寻找变得困难。须寻找一种高效的阈值计算方法对图像进行二值化。

            目前,二值化方法可分为全局阈值法、局部阈值法和动态阈值法三类。

          (1)全局阈值法。对整幅图像选取单一的阈值T进行二值化。这种方法计算速度较快,在物体和北京的灰度差别较明显时效果比较好。它将图像每个像素的灰度值与阈值T进行比较,若大于T,则取为前景色(白色);否则,取为背景色(黑色)。

          (2)局部阈值法。把图像分成若干区域,将各块图像的灰度均值作为子区域的阈值,对每个区域分别进行二值化,或对图像中的每一个像素点,根据其邻域像素点的灰度变化情况来设定一个阈值,然后逐点对图像进行二值化。这种方法速度比全局阈值法要慢,但对比较复杂或背景存在噪声的图像,用单一的阈值很难区分物体和背景,这种方法要优于全局阈值法。

           (3)动态阈值法。此方法中阈值的选择不仅取决于该像素及周围像素的灰度值,而且还与该像素的坐标位置有关。例如可以在局部上统计该区域灰度值分布特征,根据统计结果来确定不同的局部阈值。

    展开全文
  • 为解决车牌识别系统中,车牌区域由于受到光照过度、不足和...实验结果表明,文中方法运算时间仅为传统方法的61.95%,同时能更有效地克服不均匀光照对车牌图像二值化的干扰,使二值图像的汉字和字符更清晰,鲁棒性更好。
  • 自适应阈值图像二值化

    千次阅读 2020-08-13 16:08:24
    一、二值化 关于二值化的介绍,以前...图像进行二值化,且做到自适应阈值参数,有4种自适应阈值二值化方法;先从自适应阈值的作用范围来区分,自适应阈值分为: 全局阈值 使用自适应全局阈值的全局二值化方法有:大津

    一、二值化

    关于二值化的介绍,以前的博客中有介绍,这里就不再描述了,二值化介绍;二值化分为固定阈值二值化和自适应阈值二值化,固定阈值二值化方式是我们常用的二值化方式,需要自己摸索一个经验阈值,不断调整,直到找到最佳阈值,这种方式在刚刚的链接中已经介绍;而这篇文档主要介绍的就是另一种二值化方式:自适应阈值二值化。

    二、自适应阈值二值化

    图像进行二值化,且做到自适应阈值参数,有4种自适应阈值二值化方法;先从自适应阈值的作用范围来区分,自适应阈值分为:

    • 全局阈值

    使用自适应全局阈值的全局二值化方法有:大津法图像二值化、三角法图像二值化;

    • 局部阈值

    使用自适应局部阈值的局部二值化方法有:局部均值处理、局部高斯处理;

    三、大津法图像二值化

    OTSU算法也称最大类间差法,有时也称之为大津算法,由大津于1979年提出,被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

    大津法二值化适用于图像直方图中存在双峰的图像(直方图中的双峰就是指背景像素和前景像素),最佳阈值就是双峰之间的某个参数,即将背景像素和前景像素分割开,其原理就是最大类间方差法。

    大津法二值化的大致算法思路如下:

    1. 计算灰度图像的直方图,计算出0 - 255 每个像素值所占的像素个数;
    2. 遍历阈值 0 - 255,小于或等于阈值的像素为背景,大于阈值的像素为前景;
    3. 计算背景像素个数所占总像素个数的比例、背景像素的平均值;
    4. 计算前景像素个数所占总像素个数的比例、前景像素的平均值;
    5. 计算类间方差或类内方差,当使类间方差最大或者使类内方差最小的阈值,即为最佳阈值;
    6. 使用最佳阈值,对图像进行二值化处理。

    思路细化:

    1. 图像宽[w],图像高度[h],灰度阈值[T];遍历T,从0 - 255 ;
    2. 小于阈值T的像素个数[c0],c0为背景像素个数;大于阈值T的像素个数[c1],c1为前景像素个数;c0 + c1 = w * h ;
    3. 背景像素个数占总像素个数的比例[w0],w0 = c0 / (w * h) ; 前景像素个数占总像素个数的比例[w1],w1 = c1 / (w * h) ; 且w0 + w1 = 1 ;
    4. 背景的平均像素灰度值[u0],u0 = c0个背景像素灰度值之和 / c0 ;前景的平均像素灰度值[u1],u1 = c1个前景像素灰度值之和 / c1 ;
    5. 整张图像的像素灰度平均值[u],u = (c0个背景像素灰度值之和 + c1个前景像素灰度值之和) / (w * h) ;
    6. 类间方差[g],g = w0 * (u0 - u)^2 + w1 * (u1 - u)^2 ;类间方差指的是前景和背景之间的差异,显然该差异越大,说明分离度越好。
    7. 根据第(6)步,推导后类间方差g = w0 * w1 * (u0 - u1) ^ 2 ;
    8. 找到最大类间方差对应的灰度阈值T,即是最佳阈值。

    除了最大类间方差,也可以通过计算最小类内方差来得到最佳阈值,这里有篇博客介绍到:链接

    对于一些噪声较多的图像,可以先使用高斯滤波去噪,再用大津法对图像进行二值化,这样会使二值化的图像效果更好

    OpenCV中有大津法二值化的接口:

    double threshold(InputArray src, OutputArray dst, double thresh, double maxVal, int thresholdType)

    将第5个参数 thresholdType 设置成 THRESH_OTSU 即可,可以将THRESH_OTSU 和THRESH_BINARY等类型配合使用;当使用了THRESH_OTSU,函数threshold()返回值即是找到的最佳阈值,且函数中第三个参数thresh将不起作用。

     

    最大类间方差法 实现代码:

    //二值化处理,自适应阈值 大津法
    int Binarization::BinaryProcessing_OTSU(Mat& srcImg)
    {
    	//【1】安全性检查
    	if (!srcImg.data || srcImg.data == NULL) 
    	{
    		cout << "BinaryProcessing_OTSU() --> srcImg读取失败" << endl;
    		return MTC_FAIL;
    	}
    
    	//【2】图像灰度化
    	Mat grayImg;
    	cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    
    	//【3】获取最佳二值化阈值
    	int nBestTH = 0;
    	int nRet = GetBestTH_OTSU(grayImg, nBestTH);
    	if (nRet != MTC_SUCCESS) 
    	{
    		cout << "BinaryProcessing_OTSU() --> 获取最佳二值化阈值 失败" << endl;
    		return MTC_FAIL;
    	}
    	cout << "BinaryProcessing_OTSU() --> 最佳二值化阈值 = " << nBestTH << endl;
    
    	//【4】图像二值化
    	Mat binaryImg;
    	threshold(grayImg, binaryImg, nBestTH, 255, CV_THRESH_BINARY);
    
    	//【5】显示图像
    	imshow("二值化图像", binaryImg);
    
    	return MTC_SUCCESS;
    }
    
    //获取最佳阈值,自适应阈值 大津法(最大类间差法)
    int Binarization::GetBestTH_OTSU(Mat& grayImg, int& nBestTH)
    {
    	//【1】安全性检查
    	if (!grayImg.data || grayImg.data == NULL)
    	{
    		cout << "GetBestTH_OTSU() --> grayImg读取失败" << endl;
    		return MTC_FAIL;
    	}
    
    	if (grayImg.channels() != 1) 
    	{
    		cout << "GetBestTH_OTSU() --> grayImg不是灰度图像" << endl;
    		return MTC_FAIL;
    	}
    
    	//【2】参数准备
    	double sum = 0.0;			//所有像素灰度之和
    	double w0 = 0.0;			//背景像素所占比例
    	double w1 = 0.0;			//前景像素所占比例
    	double u0_temp = 0.0;
    	double u1_temp = 0.0;
    	double u0 = 0.0;			//背景平均灰度
    	double u1 = 0.0;			//前景平均灰度
    	double delta_temp = 0.0;	//类间方差
    	double delta_max = 0.0;		//最大类间方差
    	const int GrayScale = 256;
    
    	//src_image灰度级  
    	int pixel_count[GrayScale] = { 0 };		//每个灰度级的像素数目
    	float pixel_pro[GrayScale] = { 0 };		//每个灰度级的像素数目占整幅图像的比例  
    
    	int height = grayImg.rows;
    	int width = grayImg.cols;
    	//统计每个灰度级中像素的个数  
    	for (int i = 0; i < height; i++)
    	{
    		for (int j = 0; j < width; j++)
    		{
    			int index = i * width + j;
    			pixel_count[(int)grayImg.data[index]]++;		//每个灰度级的像素数目
    			sum += (int)grayImg.data[index];				//灰度之和
    		}
    	}
    	cout << "平均灰度:" << sum / (height * width) << endl;
    
    	//计算每个灰度级的像素数目占整幅图像的比例  
    	int imgArea = height * width;
    	for (int i = 0; i < GrayScale; i++)
    	{
    		pixel_pro[i] = (float)pixel_count[i] / imgArea;
    	}
    
    	//遍历灰度级[0,255],寻找合适的threshold  
    	for (int i = 0; i < GrayScale; i++)
    	{
    		w0 = w1 = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;
    		for (int j = 0; j < GrayScale; j++)
    		{
    			if (j <= i)   //背景部分  
    			{
    				w0 += pixel_pro[j];			//背景像素比例
    				u0_temp += j * pixel_pro[j];
    			}
    			else		 //前景部分  
    			{
    				w1 += pixel_pro[j];			//前景像素比例
    				u1_temp += j * pixel_pro[j];
    			}
    		}
    		u0 = u0_temp / w0;		//背景像素点的平均灰度
    		u1 = u1_temp / w1;		//前景像素点的平均灰度
    
    		delta_temp = (float)(w0 * w1 * pow((u0 - u1), 2));		//类间方差 g=w0*w1*(u0-u1)^2
    
    		//当类间方差delta_temp最大时,对应的i就是阈值T
    		if (delta_temp > delta_max)
    		{
    			delta_max = delta_temp;
    			nBestTH = i;
    		}
    	}
    
    	return MTC_SUCCESS;
    }
    

    OpenCV接口,实现代码:

    //二值化处理,自适应阈值 大津法 opencv自带接口
    int Binarization::BinaryProcessing_OTSU_OpenCV(Mat& srcImg)
    {
    	//【1】安全性检查
    	if (!srcImg.data || srcImg.data == NULL)
    	{
    		cout << "BinaryProcessing_OTSU() --> srcImg读取失败" << endl;
    		return MTC_FAIL;
    	}
    
    	//【2】图像灰度化
    	Mat grayImg;
    	cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    
    
    	//【3】图像二值化
    	Mat binaryImg;
    	double dBestTH = threshold(grayImg, binaryImg, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);		//CV_THRESH_OTSU
    	cout << "BinaryProcessing_OTSU_OpenCV() --> dBestTH = " << dBestTH << endl;
    
    	//【4】显示图像
    	imshow("二值化图像-opencv", binaryImg);
    
    	return MTC_SUCCESS;
    }

     

    四、三角法图像二值化

    三角法二值化,适用于图像直方图中存在单峰的图像,这是一种纯几何的方法来寻找最佳阈值,它的成立条件是假设直方图最大波峰在靠近最亮的一侧,然后通过三角形求得最大直线距离,根据最大直线距离对应的直方图灰度等级即为分割阈值,图示如下:

    在直方图上从最高峰处bmx到最暗对应直方图bmin(p=0)%构造一条直线,从bmin处开始计算每个对应的直方图b到直线的垂直距离,直到bmax为止,其中最大距离对应的直方图位置即为图像二值化对应的阈值T。

     

    三角法二值化算法步骤:

    (1)图像转灰度

    (2)计算图像灰度直方图

    (3)寻找直方图中两侧边界

    (4)寻找直方图最大值

    (5)检测是否最大波峰在亮的一侧,否则翻转

    (6)求解到直线的最大值

    设灰度级别为L,频率为α,当频率αmax最大的时候设L=L_αmax,当Lmin时,α=α_Lmin

    • 求解直线方程:根据点(Lmin,α_Lmin)和点(L_αmax,αmax)可以确定直线l的方程;
    • 求解各点到直线的距离:各点(L,α)到直线l的距离d,根据点到直线的距离公式可以求得,用一个列表去存放所有的距离d,然后利用max函数即可求得dmax;
    • 找到当点(L,α)到直线l的距离d最大时,灰度级别L的值即为最佳阈值;

    (7)确定最佳阈值T,如果翻转则最佳阈值为255 - T

    (8)使用最佳阈值,对图像进行二值化处理。

     

    OpenCV中有三角法二值化的接口:

    double threshold(InputArray src, OutputArray dst, double thresh, double maxVal, int thresholdType)

    将第5个参数 thresholdType 设置成 THRESH_TRIANGLE即可,可以将THRESH_TRIANGLE 和THRESH_BINARY等类型配合使用;当使用了THRESH_TRIANGLE,函数threshold()返回值即是找到的最佳阈值,且函数中第三个参数thresh将不起作用。

    几何法 实现代码:

    //二值化处理,自适应阈值 三角法
    int Binarization::BinaryProcessing_Triangle(Mat& srcImg)
    {
    	//【1】安全性检查
    	if (!srcImg.data || srcImg.data == NULL)
    	{
    		cout << "BinaryProcessing_Triangle() --> srcImg读取失败" << endl;
    		return MTC_FAIL;
    	}
    
    	//【2】图像灰度化
    	Mat grayImg;
    	cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    
    	//【3】获取最佳二值化阈值
    	int nBestTH = 0;
    	int nRet = GetBestTH_Triangle(grayImg, nBestTH);
    	if (nRet != MTC_SUCCESS)
    	{
    		cout << "BinaryProcessing_Triangle() --> 获取最佳二值化阈值 失败" << endl;
    		return MTC_FAIL;
    	}
    	cout << "BinaryProcessing_Triangle() --> 最佳二值化阈值 = " << nBestTH << endl;
    
    	//【4】图像二值化
    	Mat binaryImg;
    	threshold(grayImg, binaryImg, nBestTH, 255, CV_THRESH_BINARY);
    
    	//【5】显示图像
    	imshow("二值化图像", binaryImg);
    
    
    	return MTC_SUCCESS;
    }
    
    //获取最佳阈值,自适应阈值 三角法
    int Binarization::GetBestTH_Triangle(Mat& grayImg, int& nBestTH)
    {
    	//【1】安全性检查
    	if (!grayImg.data || grayImg.data == NULL)
    	{
    		cout << "GetBestTH_Triangle() --> grayImg读取失败" << endl;
    		return MTC_FAIL;
    	}
    
    	if (grayImg.channels() != 1)
    	{
    		cout << "GetBestTH_Triangle() --> grayImg不是灰度图像" << endl;
    		return MTC_FAIL;
    	}
    
    	//【2】参数准备
    	const int GrayScale = 256;
    	int pixel_count[GrayScale] = { 0 };		//每个灰度级的像素数目
    	int height = grayImg.rows;
    	int width = grayImg.cols;
    	int left_bound = 0;						//最左边零的位置
    	int right_bound = 0;					//最右边零的位置
    	int max_mid = 0;						//像素数量最多的灰度级位置
    	bool bIsFlipped = false;				//是否将直方图左右翻转
    
    	//【3】统计每个灰度级的像素数目
    	for (int i = 0; i < height; i++)
    	{
    		for (int j = 0; j < width; j++)
    		{
    			int index = i * width + j;
    			pixel_count[grayImg.data[index]]++;
    		}
    	}
    
    	//【4】找到最左边零的位置
    	for (int i = 0; i < GrayScale; i++)
    	{
    		if (pixel_count[i] > 0) 
    		{
    			left_bound = i;
    			break;
    		}
    	}
    
    	//位置再移动一个步长,即为最左侧零位置
    	if (left_bound > 0)
    		left_bound--;
    
    	//【5】找到最右边零的位置
    	for (int i = GrayScale - 1; i >= 0; i--)
    	{
    		if (pixel_count[i] > 0)
    		{
    			right_bound = i;
    			break;
    		}
    	}
    
    	//位置再移动一个步长,即为最右侧零位置
    	if (right_bound < GrayScale - 1)
    		right_bound++;
    
    	//【6】找到像素数量最多的灰度级位置
    	int maxNum = 0;
    	for (int i = 0; i < GrayScale; i++)
    	{
    		if (pixel_count[i] > maxNum) 
    		{
    			maxNum = pixel_count[i];
    			max_mid = i;
    		}
    	}
    
    	//【7】如果最大值(max_mid)位置落在靠左侧这样就无法满足三角法求阈值,所以要检测是否最大值(max_mid)位置是否靠近左侧
            
    	//如果靠近左侧则通过翻转到右侧位置
    	if (max_mid - left_bound < right_bound - max_mid) 
    	{
    		int i = 0;
    		int j = GrayScale - 1;
    		int temp = 0;
    		while (i < j)
    		{
    			temp = pixel_count[i];
    			pixel_count[i] = pixel_count[j];
    			pixel_count[j] = temp;
    			i++;
    			j--;
    		}
    
    		bIsFlipped = true;
    		left_bound = GrayScale - 1 - right_bound;
    		max_mid = GrayScale - 1 - max_mid;
    	}
    	  
    	//【8】计算求得阈值
    	nBestTH = left_bound;
    	int a = maxNum;
    	int b = left_bound - max_mid;
    	float maxDist = 0;
    	for (int i = left_bound + 1; i <= max_mid; i++)
    	{
    		//计算距离(点到直线的距离 (Ax + Bx + C) / 根号[A的平方 + B的平方] 
    		//因为只有 Ax+Bx 是变化的,而我们的目的是比较距离大小,所以只计算 Ax+Bx 的值)
    		float tempDist = a * i + b * pixel_count[i];
    		if (tempDist > maxDist) 
    		{
    			maxDist = tempDist;
    			nBestTH = i;
    		}
    	}
    	nBestTH--;
    
    	//【9】对已经得到的最佳阈值,如果前面已经翻转了,则阈值要用 255 - nBestTH
    	if (bIsFlipped)
    		nBestTH = GrayScale - 1 - nBestTH;
    
    	return MTC_SUCCESS;
    }
    

    OpenCV接口,实现代码:

    //二值化处理,自适应阈值 三角法 opencv自带接口
    int Binarization::BinaryProcessing_Triangle_OpenCV(Mat& srcImg)
    {
    	//【1】安全性检查
    	if (!srcImg.data || srcImg.data == NULL)
    	{
    		cout << "BinaryProcessing_Triangle_OpenCV() --> srcImg读取失败" << endl;
    		return MTC_FAIL;
    	}
    
    	//【2】图像灰度化
    	Mat grayImg;
    	cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    
    
    	//【3】图像二值化
    	Mat binaryImg;
    	double dBestTH = threshold(grayImg, binaryImg, 0, 255, CV_THRESH_BINARY | CV_THRESH_TRIANGLE);		//CV_THRESH_TRIANGLE
    	cout << "BinaryProcessing_Triangle_OpenCV() --> dBestTH = " << dBestTH << endl;
    
    	//【4】显示图像
    	imshow("二值化图像-opencv", binaryImg);
    
    	return MTC_SUCCESS;
    }

     

    五、自适应局部阈值图像二值化

    全局阈值图像二值化 只可以对整张图像使用同一个阈值进行二值化,如果图像中亮度分布不均匀,每个区域亮度都有差别,那么再使用全局阈值图像二值化,会导致部分信息缺失。

    而自适应局部阈值化能够根据图像不同区域亮度分布,来改变阈值。

     

    OpenCV中集成了这样的方法,接口如下:

    void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)

    参数介绍:

    src参数 表示输入图像(8位单通道图像);

    maxValue参数 表示使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值;

    adaptiveMethod参数 表示自适应阈值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C);

    thresholdType参数表示阈值类型,必须为THRESH_BINARY或THRESH_BINARY_INV的阈值类型;

    blockSize参数 表示块大小(奇数且大于1,比如3,5,7........ );

    C参数是常数,表示从平均值或加权平均值中减去的数。通常情况下,这是正值,但也可能为零或负值。

    (1)局部均值法图像二值化

    将参数adaptiveMethod 设置为ADAPTIVE_THRESH_MEAN_C,自适应阈值T(x, y),通过计算像素(x, y)周围blockSize x blockSize大小像素块的平均值并减去常量 C 得到。

    (2)局部高斯处理图像二值化

    将参数adaptiveMethod 设置为ADAPTIVE_THRESH_GAUSSIAN_C,自适应阈值T(x, y),通过计算像素(x, y)周围blockSize x blockSize大小像素块的加权求和(与高斯窗口相关)并减去常量 C 得到。

    如果使用平均的方法,则所有像素周围的权值相同;

    如果使用高斯的方法,则每个像素周围像素的权值则根据其到中心点的距离通过高斯方程得到。

    OpenCV接口 实现代码: 

    //自适应阈值二值化  均值
    int Binarization::AdaptiveThreshold_Mean(Mat& srcImg)
    {
    	//【1】安全性检查
    	if (!srcImg.data || srcImg.data == NULL)
    	{
    		cout << "AdaptiveThreshold_Mean() --> srcImg读取失败" << endl;
    		return MTC_FAIL;
    	}
    
    	//【2】图像灰度化
    	Mat grayImg;
    	cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    
    	//【3】自适应阈值二值化
    	Mat binaryImg;
    	adaptiveThreshold(grayImg, binaryImg, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 11, 2);
    
    	//【4】显示图像
    	imshow("二值化图像", binaryImg);
    
    	return MTC_SUCCESS;
    }
    
    
    
    //自适应阈值二值化  高斯
    int Binarization::AdaptiveThreshold_GAUSSIAN(Mat& srcImg)
    {
    	//【1】安全性检查
    	if (!srcImg.data || srcImg.data == NULL)
    	{
    		cout << "AdaptiveThreshold_GAUSSIAN() --> srcImg读取失败" << endl;
    		return MTC_FAIL;
    	}
    
    	//【2】图像灰度化
    	Mat grayImg;
    	cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    
    	//【3】自适应阈值二值化
    	Mat binaryImg;
    	adaptiveThreshold(grayImg, binaryImg, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 11, 2);
    
    	//【4】显示图像
    	imshow("二值化图像", binaryImg);
    
    	return MTC_SUCCESS;
    }

    总结

    (1)大津法的优点在于可以快速有效的找到类间分割阈值,但其缺点也很明显,就是只能针对单一目标分割,或者感兴趣的目标都属于同一灰度范围,若需探测目标灰度范围分布较大,则必将有一部分目标探测丢失。

    (2)局部分割的优点在于可以进行多目标分割,缺点在于基于局部阈值分割出的目标连结性较差,包含噪声。

     

    关于二值化,这里有几篇从OpenCV官网找到的介绍供参考:

    链接1 链接2 链接3

    展开全文
  • python与opencv图像处理基础总结,模板匹配的匹配的原理和几种常用算法,python调用opencv相关API的方法,图像二值化的处理,python调用opencv中的全局阈值函数和局部阈值函数,对图像图像阈值分割,实现图像二值化...
  • Ostu算法因其具有算法实现简单等特点成为常用的一种图像二值化算法,但其对于不均匀光照下的QR码图像二值化处理效果佳。针对Ostu算法这一缺点,提出一种解决方法:首先使用改进的同态滤波去除QR图像的不均匀光照的...
  • Android OpenCV(八):图像二值化

    千次阅读 2020-02-12 11:18:48
    图像二值化 简介 图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像...
  • 图像二值化算法

    千次阅读 2019-07-05 11:35:52
    图像二值化,首先要将原图转换成灰度图,这里展示Android代码: /** * 将彩色图转换为灰度图 * * @param img 位图 * @return 返回转换好的位图 */ public static Bitmap convertGreyImg(Bitmap img) { //...
  • 灰度图像二值化-----c++实现

    万次阅读 2013-08-13 16:47:36
    这次简单的写了灰度图像二值化。。这是什么概念呢? 图像的二值化的基本原理  图像的二值化处理就是将图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的...
  • 不均匀光照二值化算法 sauvola

    千次阅读 2017-05-09 15:52:10
    void sauvola(unsigned char * grayImage, unsigned char * biImage, int w, int h, double k, int windowSize) { int whalf = windowSize >> 1; int i, j; int IMAGE_WIDTH = w; int IMAGE_HEIGHT = h;...
  • 【数字图像处理】灰度图像二值化

    千次阅读 2019-10-08 00:56:27
    灰度图像 每副图像的每个像素对应二维空间中一个特定的位置,并且有一个或者多...灰度图像二值化 二值化:以一个值(阈值)为基准,大于(等于)这个值的数全部变为是1(或者0),小于等于这个数的就全部将他们变...
  • Otsu算法 灰度图像二值化

    千次阅读 2015-10-21 21:24:54
    Otsu方法是一种全局化的动态二值化方法,又叫大津法,是一种灰度图像二值化的常用算法。该算法的基本思想是:设使用某一个阈值将灰度图像根据灰度大小,分成目标部分和背景部分两类,在这两类的类内方差最小和类间...
  • 图像二值化应用场景二值图像定义阈值获取的方法手动阈值法自动阈值法灰度均值法基于直方图均值法OTSUTriangle自适应均值阈值分割方法总结参考文献 应用场景 二值图像处理与分析在机器视觉与机器人视觉中非常重要,...
  • 图像二值化--阈值自动选取

    万次阅读 2015-03-20 10:23:37
    图像分割是图像处理这门学科中的基础难题,基于阈值的分割则又是图像分割的最基本的难题之一,其难点在于阈值的选取。事实证明,阈值的选择的恰当与否对分割的效果起着决定性的作用。由于阈值选取对图像分割的基础性...
  • 图像二值化(黑白图)

    千次阅读 2008-09-20 19:37:00
    通过对灰度图像二值化处理,能够凸现出感兴趣目标的轮廓.灰度图像的二值化处理就是讲图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的阀值选取而获得仍然...
  • 图像进行二值化,以得到所需要的前景目标,是个古老而又重要的课题。但是这么多年来,二值化算法的效果,却往往难如人意。其核心难题,就是阈值实在太难选择了。但是,与传统的全局、局部二值化方法相比,

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,343
精华内容 10,137
关键字:

不均匀图像二值化