昊虹君 发表于 2022-12-8 12:00

使用OpenCV的函数threshold()对图像进行二值化或阈值化处理

使用OpenCV的函数threshold()对图像进行二值化或阈值化处理

如果一幅图像,其像素的灰度值只有两个取值,那么这样的图像我们就称作二值图像。
把图像转化为二值图像的过程称为图像的二值化处理。

如果对图像的灰度值按与某个值的大小关系进行新值的设置,称为叫图像的阈值化处理。

在OpenCV中,可以使用函数threshold()对图像作二值化或阈值化处理。

其原型如下:
C++原型如下:
double cv::threshold(InputArray src,
                     OutputArray dst,
                     double thresh,
                     double maxval,
                     int type)
Python原型如下:
double cv::threshold(InputArray src,
                     OutputArray dst,
                     double thresh,
                     double maxval,
                     int type)
参数意义如下:
src—输入图像,即待二值化的图像,可以是多通道,8位或32位符点型数据类型的图像,但是当参数type选择THRESH_OTSU或THRESH_TRIANGLE时,图像只能为8位的单通道图像。

dst—经过二值化处理的输出图像。

thresh—进行二值化处理的阈值。当type选择THRESH_OTSU或THRESH_TRIANGLE时,这个值被忽略,此时函数用通过OTSU法或TRIANGLE法计算出的阈值进行二值化操作。

maxval—二值化处理后的maxval值,详情见对参数type的介绍。当type选择THRESH_BINARY、THRESH_BINARY_INV、THRESH_OTSU、THRESH_TRIANGLE时会用到它,在type选择其它类型时,虽然它没有用,但也要填上它。

type—这个参数的可选枚举值及意义如下:
http://pic1.hhai.cc/pic1/2022/2022-12/001/01.png
要特别注意的是,在Python环境中,函数threshold()的返回值有两个,分别为retval和dst。
第一个retval代表函数threshold()在进行二值化处理时使用的阈值,这一点挺好,特别是对于type选择THRESH_OTSU或THRESH_TRIANGLE时,我们可以知道进行二值处理时用的阈值究竟是多少。
如果不想使用retval这个返回值,可以像下面这样调用:
_, dst = cv.threshold(src, thresh, maxval, type[, dst])
即用下划线命名返回值retval。

明白了以上各参数的意义和可取值后,就基本了解了函数threshold()的使用,接下来再看看示例代码就能完全掌握了。

首先是当type取值为THRESH_BINARY 、THRESH_BINARY_INV 、THRESH_TRUNC、THRESH_TOZERO 、THRESH_TOZERO_INV 时的示例代码。

当type取值为THRESH_BINARY 、THRESH_BINARY_INV 、THRESH_TRUNC、THRESH_TOZERO 、THRESH_TOZERO_INV 时的Python代码如下:

# -*- coding: utf-8 -*-
# 出处:昊虹AI笔记网(hhai.cc)
# 用心记录计算机视觉和AI技术

# 博主微信/QQ 2487872782
# QQ群 271891601
# 欢迎技术交流与咨询

# OpenCV的版本为4.4.0

import numpy as np
import cv2 as cv

if __name__ == '__main__':
    A1 = np.array([,
                   ], dtype='uint8')

    thresh1 = 80
    maxval1 = 200
    retval1, B1 = cv.threshold(A1, thresh1, maxval1, cv.THRESH_BINARY)
    retval2, B2 = cv.threshold(A1, thresh1, maxval1, cv.THRESH_BINARY_INV)
    retval3, B3 = cv.threshold(A1, thresh1, maxval1, cv.THRESH_TRUNC)
    retval4, B4 = cv.threshold(A1, thresh1, maxval1, cv.THRESH_TOZERO)
    retval5, B5 = cv.threshold(A1, thresh1, maxval1, cv.THRESH_TOZERO_INV)

运行结果如下:
http://pic1.hhai.cc/pic1/2022/2022-12/001/02.png

http://pic1.hhai.cc/pic1/2022/2022-12/001/03.png

当type取值为THRESH_BINARY 、THRESH_BINARY_INV 、THRESH_TRUNC、THRESH_TOZERO 、THRESH_TOZERO_INV 时的C++代码如下:

//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;


int main()
{

        cv::Mat A1 = (cv::Mat_<uchar>(2, 3) << 0, 10, 50,
                                                   80, 150, 255);
        cout << "A1中的数据为:\n" << A1 << endl << endl;

       
        double thresh1 = 80;
        double maxval1 = 200;

        Mat B1, B2, B3, B4, B5;

        threshold(A1, B1, thresh1, maxval1, THRESH_BINARY);
        cout << "B1中的数据为:\n" << B1 << endl << endl;

        threshold(A1, B2, thresh1, maxval1, THRESH_BINARY_INV);
        cout << "B2中的数据为:\n" << B2 << endl << endl;

        threshold(A1, B3, thresh1, maxval1, THRESH_TRUNC);
        cout << "B3中的数据为:\n" << B3 << endl << endl;

        threshold(A1, B4, thresh1, maxval1, THRESH_TOZERO);
        cout << "B4中的数据为:\n" << B4 << endl << endl;

        threshold(A1, B5, thresh1, maxval1, THRESH_TOZERO_INV);
        cout << "B5中的数据为:\n" << B5 << endl << endl;

        return(0);
}
运行结果如下:
http://pic1.hhai.cc/pic1/2022/2022-12/001/04.png
然后是当type取值为THRESH_OTSU 、THRESH_TRIANGLE时的示例代码。

下面的示例代码中用到的图像下载链接如下:
https://pan.baidu.com/s/1PqeJG6EbONmYg03jYQb2MQ?pwd=xu7b

当type取值为THRESH_OTSU 、THRESH_TRIANGLE时的Python示例代码如下:

# -*- coding: utf-8 -*-
# 出处:昊虹AI笔记网(hhai.cc)
# 用心记录计算机视觉和AI技术

# 博主微信/QQ 2487872782
# QQ群 271891601
# 欢迎技术交流与咨询

# OpenCV的版本为4.4.0

import cv2 as cv
import sys

image = cv.imread('F:/material/images/2022/2022-06/img_300_320.jpg')
if image is None:
    print('Error: Could not load image')
    sys.exit()

# cv.imshow('Source Image', image)

img_gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow('img_gray', img_gray)

thresh1 = 0
maxval1 = 250

OTSU_threshold, img_B1 = cv.threshold(img_gray, thresh1, maxval1, cv.THRESH_OTSU)
TRIANGLE_threshold, img_B2 = cv.threshold(img_gray, thresh1, maxval1, cv.THRESH_TRIANGLE)

cv.imshow('img_OTSU', img_B1)
cv.imshow('img_TRIANGLE', img_B2)

cv.waitKey(0)
cv.destroyAllWindows()
运行结果如下:
http://pic1.hhai.cc/pic1/2022/2022-12/001/05.png

http://pic1.hhai.cc/pic1/2022/2022-12/001/06.png
                                          
http://pic1.hhai.cc/pic1/2022/2022-12/001/07.png
                                          
http://pic1.hhai.cc/pic1/2022/2022-12/001/08.png
从上面的运行结果可以看出,
利用OTSU算法找到的阈值为135;
利用Triangle算法找到的阈值为203。
并且,函数threshold()当type选择为THRESH_OTSU和THRESH_TRIANGLE时,将低于阈值的值置为0,将高于阈值的值置为我们设定的maxval1 = 250。

当type取值为THRESH_OTSU 、THRESH_TRIANGLE时的C++示例代码如下:

//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
        // 读取源图像
        cv::Mat image = cv::imread("F:/material/images/2022/2022-06/img_300_320.jpg", 1);
        if (image.empty())
                return -1;

        //imshow("image", image);

        Mat img_gray;

        cvtColor(image, img_gray, COLOR_BGR2GRAY);
        imshow("img_gray", img_gray);

        Mat img_B1, img_B2;
        double thresh1 = 0;
        double maxval1 = 250;

        threshold(img_gray, img_B1, thresh1, maxval1, THRESH_OTSU);
        threshold(img_gray, img_B2, thresh1, maxval1, THRESH_TRIANGLE);

        imshow("img_B1", img_B1);
        imshow("img_B2", img_B2);


        cv::waitKey(0);
        return 0;
}
运行结果如下:
http://pic1.hhai.cc/pic1/2022/2022-12/001/09.png
页: [1]
查看完整版本: 使用OpenCV的函数threshold()对图像进行二值化或阈值化处理