[OpenCv] 自适应阀值的二值化处理

#include <iostream>
#include <cv.h>
#include <highgui.h>

using namespace std;
double TwoDimentionOtsu(IplImage *image);
int main()  
{ 
        IplImage* srcImage = cvLoadImage( "C:\\Users\\Administrator\\Desktop\\111.jpg",0 ); 
        assert(NULL != srcImage);

        cvNamedWindow("src",0);
        cvShowImage("src",srcImage); 

       // clock_t start_time=clock();

        //计算最佳阈值 
        double threshold = TwoDimentionOtsu(srcImage);//70,125

      //  clock_t end_time=clock();
       // cout<< "Running time is: "<<static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000<<"ms"<<endl;//输出运行时间

      //  cout << "threshold=" << threshold << endl;

        IplImage* biImage = cvCreateImage(cvGetSize(srcImage),8,1);  
        //对图像二值化
        //cvThreshold(srcImage,biImage,255,255, CV_THRESH_OTSU | CV_THRESH_BINARY);
        cvThreshold(srcImage,biImage,threshold,255, CV_THRESH_BINARY);

        cvNamedWindow("binary",0);  
        cvShowImage("binary",biImage);  

        cvWaitKey(0);  

        cvReleaseImage(&srcImage);  
        cvReleaseImage(&biImage);  

        cvDestroyAllWindows();  

        return 0;  
} 
double TwoDimentionOtsu(IplImage *image)
{
        double t0 = 0, s0 = 0, t = 0, s = 0;
        int width = image->width;  
        int height = image->height; 
        double dHistogram[256][256]={0.0};                                //建立二维灰度直方图  
        unsigned long sum0 = 0,sum1 = 0;                                //sum0记录所有的像素值的总和,sum1记录3x3窗口的均值的总和
        uchar* data = (uchar*)image->imageData; 
        for(int i=0; i<height; i++)  
        {  
                for(int j=0; j<width; j++)  
                {  
                        unsigned char nData1 = data[i * image->widthStep + j];//nData1记录当前点(i,j)的像素值
                        sum0 += nData1;
                        unsigned char nData2 = 0;  //nData2记录以当前点(i,j)为中心三领域像素值的平均值
                        int nData3 = 0;                                        //nData3记录以当前点(i,j)为中心三领域像素值之和,注意9个值相加可能超过一个字节  
                        for(int m=i-1; m<=i+1; m++)  
                        {  
                                for(int n=j-1; n<=j+1; n++)  
                                {  
                                        if((m>=0)&&(m<height)&&(n>=0)&&(n<width))
                                                nData3 += data[m * image->widthStep + n];
                                }  
                        }  
                        nData2 = (unsigned char)(nData3/9);    //对于越界的索引值进行补零,邻域均值
                        sum1 += nData2;
                        dHistogram[nData1][nData2]++;  
                }  
        }

        long N = height*width;                //总像素数  
        t = sum0/N;                                        //图像灰度级均值
        s = sum1/N;                                        //邻域平均灰度级的均值

        s0 = s;
        t0 = t; 
        for(int j=0; j<256; j++)
                for(int i=0; i<256; i++) 
                {
                        dHistogram[i][j] = dHistogram[i][j]/N;  //得到归一化的概率分布 
                }

                double w0 = 0.0,w1 = 0.0,u0i = 0.0,u1i = 0.0,u0j = 0.0,u1j = 0.0;

                do
                {
                        t0 = t;
                        s0 = s;
                        w0 = w1 = u0i = u1i = u0j = u1j = 0.0;
                        for (int i = 0,j; i < 256; i++)
                        {
                                for (j = 0; j < s0; j++)
                                {
                                        w0 += dHistogram[i][j];
                                        u0j += dHistogram[i][j] * j;
                                }

                                for (; j < 256; j++)
                                {
                                        w1 += dHistogram[i][j];
                                        u1j += dHistogram[i][j] * j;
                                }

                        }
                        for (int j = 0,i = 0; j < 256; j++)
                        {
                                for (i = 0; i < t0; i++)
                                        u0i += dHistogram[i][j] * i;
                                for (; i < 256; i++)
                                        u1i += dHistogram[i][j] * i;
                        }
                        u0i /= w0;
                        u1i /= w1 ;
                        u0j /= w0;
                        u1j /= w1;

                        t = (u0i + u1i)/2;
                        s = (u0j + u1j)/2;
                }while ( t != t0);//是否可以用这个做为判断条件,有待考究,请高手指点

                return t;//只用t做为阈值,个人也感觉不妥,但没有找到更好的方法,请高手指点

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OpenCV中的自适应二值化是一种图像处理方法,用于在同一幅图像上不同部分具有不同亮度的情况下,根据每个小区域计算对应的阈值,并将图像二值化。这样可以在亮度不同的情况下得到更好的结果。 自适应二值化的函数为cv2.adaptiveThreshold(),它有以下几个参数: 1. 原始图像 2. 像素值上限 3. 自适应方法:cv2.ADAPTIVE_THRESH_MEAN_C表示区域内均值,cv2.ADAPTIVE_THRESH_GAUSSIAN_C表示区域内像素点加权和,权重为一个高斯窗口 4. 值的赋值方法:只有cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV 5. 区域大小:规定区域大小为一个正方形的区域 6. 常数C:与方法有关的参数,阈值等于均值或加权值减去这个常数(为0相当于阈值就是求得区域内均值或加权值) 通过调整这些参数,可以根据具体的需求对图像进行自适应二值化处理。这样可以在处理含有不同亮度的图像时,得到更好的效果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [opencv自适应二值化的应用](https://blog.csdn.net/weixin_43868552/article/details/126939961)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [三、OpenCV图像的预处理——二值化自适应阈值](https://blog.csdn.net/qq_34440409/article/details/120551622)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丶布布

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值