文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

目标

在本教程中,您将学习如何:

  • 使用OpenCV函数threshold执行基本阈值操作

理论

注意

下面的解释属于由Bradski和Kaehler编写的Learning OpenCV一书。


什么是阈值?

  • 它是一种最简单的分割方法

  • 应用示例:分离出我们想要分析的对象的图像区域。 该分离基于对象像素和背景像素之间的强度变化。

  • 为了从剩余部分(其将最终被丢弃)区分出我们感兴趣的像素,我们将每个像素强度值与阈值(根据要解决的问题确定)相比较。

  • 一旦我们正确地分离了重要像素,我们就可以用确定的值来设置它们以识别它们(即,我们可以为它们分配一个0 (黑色),255(白色)或任何满足您需要的值)。

    Threshold simple example
第 1 段(可获 2 积分)

阈值类型

  • OpenCV提供了执行阈值操作的函数threshold

  • 我们可以使用此函数实现5 种类型的阈值操作。 我们将在以下小节解释它们。

  • 为了说明这些阈值处理过程如何工作,假设我们有一张源图像其像素强度值为src(x,y)。 下面的图片描述了这一点。 水平蓝线表示阈值thresh(固定)。

    Threshold Binary

阈值二进制

  • 该阈值操作可以表示为:

    \texttt{dst} (x,y) = \fork{\texttt{maxVal}}{if $\texttt{src}(x,y)> \texttt{thresh}$}{0}{otherwise}

  • 因此,如果像素src(x,y) 的强度高于thresh,则新的像素强度被设置为 MaxVal. 否则,像素设置为 0.

    Threshold Binary
第 2 段(可获 2 积分)

阈值二进制,反相

  • 该阈值操作可以表示为:

    \texttt{dst} (x,y) = \fork{0}{if $\texttt{src}(x,y)> \texttt{thresh}$}{\texttt{maxVal}}{otherwise}

  • 如果像素src(x,y) 的强度高于 thresh,则新的像素强度被设置为 0. 否则,设置为 MaxVal.

    Threshold Binary Inverted

截断

  • 该阈值操作可以表示为:

    \texttt{dst} (x,y) = \fork{\texttt{threshold}}{if $\texttt{src}(x,y)> \texttt{thresh}$}{\texttt{src}(x,y)}{otherwise}

  • 像素的最大强度值是 thresh,如果 src(x,y) 比它大,则其值被截断。 见下图:

    Threshold Truncate

阈值为零

  • 该操作可以表示为:

    \texttt{dst} (x,y) = \fork{\texttt{src}(x,y)}{if $\texttt{src}(x,y)> \texttt{thresh}$}{0}{otherwise}

  • 如果 src(x,y) 的值比 thresh小,则新的像素值将被设置为 0.

    Threshold Zero

阈值为零,反相

  • 该操作可以表示为:

    \texttt{dst} (x,y) = \fork{0}{if $\texttt{src}(x,y)> \texttt{thresh}$}{\texttt{src}(x,y)}{otherwise}

  • 如果src(x,y) 的值比thresh大, 则新的像素值将被设置为 0.

    Threshold Zero Inverted
第 3 段(可获 2 积分)

代码

下面是本教程的示例代码,可也可以直接从这里 下载

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

/// Global variables

int threshold_value = 0;
int threshold_type = 3;;
int const max_value = 255;
int const max_type = 4;
int const max_BINARY_value = 255;

Mat src, src_gray, dst;
char* window_name = "Threshold Demo";

char* trackbar_type = "Type: \n 0: Binary \n 1: Binary Inverted \n 2: Truncate \n 3: To Zero \n 4: To Zero Inverted";
char* trackbar_value = "Value";

/// Function headers
void Threshold_Demo( int, void* );

/**
 * @function main
 */
int main( int argc, char** argv )
{
  /// Load an image
  src = imread( argv[1], 1 );

  /// Convert the image to Gray
  cvtColor( src, src_gray, CV_BGR2GRAY );

  /// Create a window to display results
  namedWindow( window_name, CV_WINDOW_AUTOSIZE );

  /// Create Trackbar to choose type of Threshold
  createTrackbar( trackbar_type,
                  window_name, &threshold_type,
                  max_type, Threshold_Demo );

  createTrackbar( trackbar_value,
                  window_name, &threshold_value,
                  max_value, Threshold_Demo );

  /// Call the function to initialize
  Threshold_Demo( 0, 0 );

  /// Wait until user finishes program
  while(true)
  {
    int c;
    c = waitKey( 20 );
    if( (char)c == 27 )
      { break; }
   }

}


/**
 * @function Threshold_Demo
 */
void Threshold_Demo( int, void* )
{
  /* 0: Binary
     1: Binary Inverted
     2: Threshold Truncated
     3: Threshold to Zero
     4: Threshold to Zero Inverted
   */

  threshold( src_gray, dst, threshold_value, max_BINARY_value,threshold_type );

  imshow( window_name, dst );
}
第 4 段(可获 2 积分)

说明

  1. 让我们检查一下程序的总体结构:

    • 加载图像。 如果是BGR格式,我们将其转换为灰度格式。记住,我们可以使用函数 cvtColor实现转换:

      src = imread( argv[1], 1 );
      
      /// Convert the image to Gray
      cvtColor( src, src_gray, CV_BGR2GRAY );
      
    • 创建一个窗口以显示结果

      namedWindow( window_name, CV_WINDOW_AUTOSIZE );
      
    • 创建2个滑动条供用户输入:

      • 阈值类型: 二进制,零等等...
      • 阈值
      createTrackbar( trackbar_type,
                   window_name, &threshold_type,
                   max_type, Threshold_Demo );
      
      createTrackbar( trackbar_value,
                   window_name, &threshold_value,
                   max_value, Threshold_Demo );
      
    • 等待用户输入阈值,阈值类型(或直到程序退出)

    • 每当用户更改滑动条的值时,将调用Threshold_Demo函数:

      /**
       * @function Threshold_Demo
       */
      void Threshold_Demo( int, void* )
      {
        /* 0: Binary
           1: Binary Inverted
           2: Threshold Truncated
           3: Threshold to Zero
           4: Threshold to Zero Inverted
         */
      
        threshold( src_gray, dst, threshold_value, max_BINARY_value,threshold_type );
      
        imshow( window_name, dst );
      }
      

      如您所见,函数threshold被调用。 有以下5个参数:

      • src_gray:我们的输入图像
      • dst:目标(输出)图像
      • threshold_value: 进行阈值处理操作的thresh 值
      • max_BINARY_value:用于二进制阈值操作的值(用于设置所选像素)
      • threshold_type: :5钟阈值操作之一。 它们列在上面函数的注释部分。
第 5 段(可获 2 积分)

结果

  1. 编译此程序后,使用图像的所在路径作为参数运行它。 例如,对于如下的输入图像:

    Threshold Original Image
  2. 首先,我们尝试用二进制阈值反向来限制我们的图像。 我们预期那些比thresh 亮的像素会变暗,确实如此,我们可以从下面的快照中看到(注意原始图像,小狗的舌头和眼睛与图像相比更加明亮,这些反映在输出图像中)。

    Threshold Result Binary Inverted
  3. 现在我们尝试阈值为零。 这样,我们期望最暗的像素(低于阈值)将完全变成黑色,而值大于阈值的像素将保持其原始值。 这可以通过以下输出图像的快照进行验证:

    Threshold Result Zero
第 6 段(可获 2 积分)

文章评论