OpenCV全局/局部阀值二值化

1.概念


1.1全局二值化


根据自定义阀值对图像进行二值化处理,即灰度值大于阀值时设改像素灰度值为255,灰度值小于阈值时设该像素灰度值为0

1.2局部二值化


在局部范围内根据特定算法算出局部的阀值,这个局部的大小可以自己决定(例8*8),算法也可以自己觉得,本文所用的用法是局部平局的灰度值作为阀值。得到局部阀值再进行局部二值化处理


2.局部二值化结果


原图

局部二值化结果

3.完整代码

#include "cv.h"                         
#include "highgui.h"
#include "cvaux.h"
#include "cxcore.h"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <string>

using namespace cv;
using namespace std;

Mat image3;
Mat target3;

//全局阈值二值化
void globalTwoValue(Mat src,int value)
{
    target3 = Mat::zeros(src.size(), src.type());

    for (int i = 0; i < src.rows; i++)
    {
        for (int j = 0; j < src.cols; j++)
        {

                break;
            if (value > (int)src.at<uchar>(i, j))
                target3.at<uchar>(i, j) = 0;
            else
                target3.at<uchar>(i, j) = 255;

        }
    }
}
//8*8局部二值化,阈值=局部平均灰度值
void localTwoValue(Mat src)
{
    //1.先算出一列有几个8,剩下几个像素
    int countRow = src.rows / 8;
    int rowLeft = src.rows % 8;

    //2.算出一列有几个8,剩下几个像素
    int countCol = src.cols / 8;
    int colLeft = src.cols % 8;


    target3 = Mat::zeros(src.size(), src.type());

    for (int k = 0; k < countRow; k++)
    {
        for (int l = 0; l < countCol; l++)
        {
            int value = 0;
            for (int i = k * 8; i < (k + 1) * 8; i++)
            {
                for (int j = l * 8; j < (l + 1) * 8; j++)
                {
                    value += (int)src.at<uchar>(i, j);
                }
            }
            value = value / 64;
            for (int i = k*8; i < (k + 1) * 8; i++)
            {
                for (int j = l * 8; j < (l + 1) * 8; j++)
                {
                    if ((int)src.at<uchar>(i, j) < value )
                        target3.at<uchar>(i, j) = 0;
                    else
                        target3.at<uchar>(i, j) = 255;
                }
            }
        }
    }

    //底部不足8*8部分
    if (rowLeft != 0)
    {
        for (int k = countRow; k < countRow + rowLeft; k++)
        {
            for (int l = 0; l < countCol; l++)
            {
                int value = 0;
                for (int i = countRow * 8; i < countRow * 8 + rowLeft; i++)
                {
                    for (int j = l * 8; j < (l + 1) * 8; j++)
                    {
                        value += (int)src.at<uchar>(i, j);
                    }
                }
                value = value / (8 * rowLeft);
                for (int i = countRow * 8; i < countRow * 8 + rowLeft; i++)
                {
                    for (int j = l * 8; j < (l + 1) * 8; j++)
                    {
                        if ((int)src.at<uchar>(i, j) < value)
                            target3.at<uchar>(i, j) = 0;
                        else
                            target3.at<uchar>(i, j) = 255;
                    }
                }
            }
        }
    }
    //右侧不足8*8部分
    if (colLeft != 0)
    {
        for (int k = 0; k < countRow; k++)
        {
            for (int l = countCol; l < countCol + colLeft; l++)
            {
                int value = 0;
                for (int i = k * 8; i < (k + 1) * 8; i++)
                {
                    for (int j = countCol * 8; j < countCol * 8 + colLeft; j++)
                    {
                        value += (int)src.at<uchar>(i, j);
                    }
                }
                value = value / (8 * colLeft);
                for (int i = k * 8; i < (k + 1) * 8; i++)
                {
                    for (int j = countCol * 8; j < countCol * 8 + colLeft; j++)
                    {
                        if ((int)src.at<uchar>(i, j) < value)
                            target3.at<uchar>(i, j) = 0;
                        else
                            target3.at<uchar>(i, j) = 255;
                    }
                }
            }
        }
    }
    //右下角 rowleft * colleft 部分
    if (rowLeft != 0 && colLeft != 0)
    {
        int value = 0;
        for (int i = 8 * countRow; i < src.rows; i++)
        {
            for (int j = 8 * countCol; j < src.cols; j++)
            {
                value += (int)src.at<uchar>(i, j);
            }
        }
        value = value / (rowLeft * colLeft);
        for (int i = 8 * countRow; i < src.rows; i++)
        {
            for (int j = 8 * countCol; j < src.cols; j++)
            {
                if ((int)src.at<uchar>(i, j) < value)
                    target3.at<uchar>(i, j) = 0;
                else
                    target3.at<uchar>(i, j) = 255;
            }
        }
    }

}


int main()
{
    //加上0表示读入灰度图
    image3 = imread("D:/opencv/testPic/d1.bmp", 0);

    if (image3.empty())
    {
        printf("could not load pic!\n");
        return -1;
    }

    namedWindow("image3");

    imshow("image3", image3);

    localTwoValue(image3);

    namedWindow("target3");

    imshow("target3", target3);

    imwrite("D:/opencv/testPic/d4.bmp", target3);

    waitKey(0);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值