OpenCV-阈值处理

12 篇文章 0 订阅
5 篇文章 0 订阅

基础知识

基本方法

OpenCV中已经实现了常用的阈值处理方式,可以通过关键字进行选择(开头均以 THRESH 表示):

阈值 thresh , 值 maxval 对应函数 threshold 中的 maxval.
在这里插入图片描述

1. THRESH_BINARY
大于thresh的置为 maxval , 小于 thresh 的置为 0;
dst ⁡ ( x , y ) = {  maxval   if  src ⁡ ( x , y ) >  thresh  0  otherwise  \operatorname{dst}(x, y)=\left\{\begin{array}{ll} \text { maxval } & \text { if } \operatorname{src}(x, y)>\text { thresh } \\ 0 & \text { otherwise } \end{array}\right. dst(x,y)={ maxval 0 if src(x,y)> thresh  otherwise 
2. THRESH_BINARY_INV
对上面取反
dst ⁡ ( x , y ) = { 0  if  src ⁡ ( x , y ) >  thresh   maxval   otherwise  \operatorname{dst}(x, y)=\left\{\begin{array}{ll} 0 & \text { if } \operatorname{src}(x, y)>\text { thresh } \\ \text { maxval } & \text { otherwise } \end{array}\right. dst(x,y)={0 maxval  if src(x,y)> thresh  otherwise 
3. THRESH_TRUNC
大于阈值thresh的取 thresh,小于阈值的不变
dst ⁡ ( x , y ) = {  threshold   if  src ⁡ ( x , y ) >  thresh  src ⁡ ( x , y )  otherwise  \operatorname{dst}(x, y)=\left\{\begin{array}{ll} \text { threshold } & \text { if } \operatorname{src}(x, y)>\text { thresh } \\ \operatorname{src}(x, y) & \text { otherwise } \end{array}\right. dst(x,y)={ threshold src(x,y) if src(x,y)> thresh  otherwise 
4. THRESH_TOZERO
大于阈值thresh的取 当前值 src,小于阈值的置0
dst ⁡ ( x , y ) = { src ⁡ ( x , y )  if  src ⁡ ( x , y ) >  thresh  0  otherwise  \operatorname{dst}(x, y)=\left\{\begin{array}{ll} \operatorname{src}(x, y) & \text { if } \operatorname{src}(x, y)>\text { thresh } \\ 0 & \text { otherwise } \end{array}\right. dst(x,y)={src(x,y)0 if src(x,y)> thresh  otherwise 
5. THRESH_TOZERO_INV
对上面取反
dst ⁡ ( x , y ) = { 0  if  src ⁡ ( x , y ) >  thresh  src ⁡ ( x , y )  otherwise  \operatorname{dst}(x, y)=\left\{\begin{array}{ll} 0 & \text { if } \operatorname{src}(x, y)>\text { thresh } \\ \operatorname{src}(x, y) & \text { otherwise } \end{array}\right. dst(x,y)={0src(x,y) if src(x,y)> thresh  otherwise 

图形表示

在这里插入图片描述

OTSU 大津法

适用于双峰阈值
将图像中的像素分为前景像素与背景像素,当前景像素集合与背景像素集合之间的类间方差最大时所对应的阈值,即为该图像的最优阈值。
通俗理解为: 图像直方图中两个波峰(前景像素、背景像素)之间的最低谷所对应的像素值。

Halcon演示

TRIANGLE 算法

适用于单峰阈值
基于直方图数据,阈值最高点与最低点构成一条直线,求直方图上的每一点到该直线的距离,最大的距离即为所选取的阈值。
在这里插入图片描述
在这里插入图片描述

自适应阈值方法

以上都是固定阈值,即全局阈值,缺少对细节的把握。而自适应阈值,又称为局部阈值,对于每个点及其周围区域的像素值计算阈值,以此进行二值化。这样可以较好的效果,但是计算量偏大。
OpenCV中有两种计算方式,一个是 基于平均灰度基于高斯函数
在这里插入图片描述
函数原型为:
在这里插入图片描述
其中 maxValue与全局阈值中 maxval 含义相同,大于/小于 阈值将其置为 maxValue。blockSize指计算阈值的区域大小,大的区域计算速度快,小的区域细节处理较好,需要根据实际情况进行取舍。上述方式计算出来的阈值减去C即为所采用的阈值。C一般为正值。

实验验证

为直观的显示阈值处理的结果,采用创建滚动条的方式(createTrankbar函数)进行演示。
这里使用函数中的data传递数据,避免声明一大堆全局变量。
实验结果

程序

main.cpp


//
// Created by zzl on 2021/1/11.
//
// 对圆锥体进行单目测距

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

// OpenCV
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/calib3d.hpp"

using namespace std;
using namespace cv;

enum Threshold {
    BINARY, BINARY_INV, TRUNC, TOZERO, TOZERO_INV, OTSU, TRIANGLE, ADA_MEAN, ADA_GAUSS
};



class myDatatype {
public:
    Mat &srcImg;
    Mat &dstImg;
    string winNames;
    int methods;

    myDatatype(Mat &srcImg_, Mat &dstImg_, string winNames_,int me_) : srcImg(srcImg_), dstImg(dstImg_),
                                                                             winNames(winNames_),methods(me_){}
};

void onChange(int pos, void *Data) {
    myDatatype data = *(myDatatype *) Data;
    if(data.methods < 7){
        threshold(data.srcImg, data.dstImg, pos, 255, data.methods);
    }else{
        adaptiveThreshold(data.srcImg,data.dstImg,255,data.methods,THRESH_BINARY_INV,5,5);
        // 修改 thresholdType 的值 为 THRESH_BINARY_INV 或 THRESH_BINARY、blockSize大小、C的值
        //adaptiveThreshold(data.srcImg,data.dstImg,255,data.methods,THRESH_BINARY,5,0);
    }
    imshow(data.winNames, data.dstImg);
}

int main(int argc, char **argv) {
    Mat src = imread("/home/zzl/Blog/MonoMeasure/model/2.png", 1); // 输入图像
    Mat src_gray;
    cvtColor(src, src_gray, COLOR_BGR2GRAY);
    string windowName = "Display";
    namedWindow(windowName, WINDOW_NORMAL);
    moveWindow(windowName, 1800, 200);
    resizeWindow(windowName,Size(800,800));
    imshow(windowName, src);
    waitKey();

    // 阈值处理

    Mat dst_thres = Mat::zeros(src_gray.size(), CV_8UC1);
    int methods = 0;
    myDatatype Data(src_gray, dst_thres, windowName,methods);
    int initValue = 30;

 	// 创建滑动条
    createTrackbar("Threshold", windowName, &initValue, 255, onChange, &Data); // 使用自己创建的类传递数据,避免声明一大堆全局变量
    createTrackbar("Methods", windowName, &methods, 8, onChange, &Data);
    waitKey();

    cout << "Hello World" << endl;
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.17)
project(Threshold)

set(CMAKE_CXX_STANDARD 14)

find_package(OpenCV 4 REQUIRED)
message(STATUS "OpenCV library status:")
message(STATUS "   OpenCV Version: ${OpenCV_VERSION}" )
include_directories(${OpenCV_INCLUDES})

add_executable(Threshold main.cpp )
target_link_libraries(Threshold${OpenCV_LIBS} )

参考博客:

https://blog.csdn.net/qq_45769063/article/details/107102117

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值