OpenCV入门(十二)-- 阈值化

阈值化

阈值化的基本思想是:给定一个数组和一个阈值,然后根据数组中的每个元素是低于还是高于阈值而进行一些处理。

函数声明:

Threshold

对数组元素进行固定阈值操作

void cvThreshold( const CvArr* src, CvArr* dst, double threshold,
                  double max_value, int threshold_type );
src
原始数组 (单通道 , 8-bit of 32-bit 浮点数).
dst
输出数组,必须与 src 的类型一致,或者为 8-bit.
threshold
阈值
max_value
使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值.
threshold_type
阈值类型 (见讨论)

函数 cvThreshold 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像。(cvCmpS 也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像点。本函数支持的对图像取阈值的方法由 threshold_type 确定:

threshold_type=CV_THRESH_BINARY:
dst(x,y) = max_value, if src(x,y)>threshold
           0, otherwise

threshold_type=CV_THRESH_BINARY_INV:
dst(x,y) = 0, if src(x,y)>threshold
           max_value, otherwise

threshold_type=CV_THRESH_TRUNC:
dst(x,y) = threshold, if src(x,y)>threshold
           src(x,y), otherwise

threshold_type=CV_THRESH_TOZERO:
dst(x,y) = src(x,y), if (x,y)>threshold
           0, otherwise

threshold_type=CV_THRESH_TOZERO_INV:
dst(x,y) = 0, if src(x,y)>threshold
           src(x,y), otherwise

下面是图形化的阈值描述:

Image:threshold.png


实现代码:

/*
* 阈值化
*/

#include "highgui.h"
#include "cv.h"
#include<stdio.h>

void sum_rgb(IplImage* img, IplImage* dst);

void doThreshold(IplImage* img)
{
	IplImage* dst = cvCreateImage(
		cvGetSize(img),
		img->depth,
		1
		);
	sum_rgb(img,dst);
	
	cvNamedWindow("thresh");
	cvShowImage("thresh",dst);

	while(1)
	{
		if((cvWaitKey(10) & 0x7f) == 27)
		{
			break;
		}
	}
	cvDestroyWindow("thresh");
	cvReleaseImage(&img);
	cvReleaseImage(&dst);
}

void sum_rgb(IplImage* img, IplImage* dst)
{
	IplImage* r = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	IplImage* g = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	IplImage* b = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);

	cvSplit(img, r, g, b, NULL);

	IplImage* s = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);

	cvAddWeighted(r, 1./3., g, 1./3., 0.0, s);
	cvAddWeighted(s, 2./3., b, 1./3., 0.0, s);

	//IplImage* s = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);
	//cvZero(s);
	//cvAcc(b,s);
	//cvAcc(g,s);
	//cvAcc(r,s);

	cvThreshold(s, dst, 100, 100, CV_THRESH_TRUNC);
	//cvConvertScale(s, dst, 1,0);

	cvReleaseImage(&r);
	cvReleaseImage(&g);
	cvReleaseImage(&b);
	cvReleaseImage(&s);
}

实现结果:


用注释部分的程序替换:另一种组合不同通道,并阈值化图像的方法

/*
* 阈值化
*/

#include "highgui.h"
#include "cv.h"
#include<stdio.h>

void sum_rgb(IplImage* img, IplImage* dst);

void doThreshold(IplImage* img)
{
	IplImage* dst = cvCreateImage(
		cvGetSize(img),
		img->depth,
		1
		);
	sum_rgb(img,dst);
	
	cvNamedWindow("thresh");
	cvShowImage("thresh",dst);

	while(1)
	{
		if((cvWaitKey(10) & 0x7f) == 27)
		{
			break;
		}
	}
	cvDestroyWindow("thresh");
	cvReleaseImage(&img);
	cvReleaseImage(&dst);
}

void sum_rgb(IplImage* img, IplImage* dst)
{
	IplImage* r = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	IplImage* g = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	IplImage* b = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);

	cvSplit(img, r, g, b, NULL);

	//IplImage* s = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);

	//cvAddWeighted(r, 1./3., g, 1./3., 0.0, s);
	//cvAddWeighted(s, 2./3., b, 1./3., 0.0, s);

	IplImage* s = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);
	cvZero(s);
	cvAcc(b,s);
	cvAcc(g,s);
	cvAcc(r,s);

	cvThreshold(s, dst, 100, 100, CV_THRESH_TRUNC);
	cvConvertScale(s, dst, 1,0);

	cvReleaseImage(&r);
	cvReleaseImage(&g);
	cvReleaseImage(&b);
	cvReleaseImage(&s);
}

结果:



自适应阈值

这是一种改进的阈值技术,其中阈值本身是一个变量。

函数声明:

AdaptiveThreshold

自适应阈值方法

void cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value,
                          int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C,
                          int threshold_type=CV_THRESH_BINARY,
                          int block_size=3, double param1=5 );
src
输入图像.
dst
输出图像.
max_value
使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值.
adaptive_method
自适应阈值算法使用:CV_ADAPTIVE_THRESH_MEAN_C 或 CV_ADAPTIVE_THRESH_GAUSSIAN_C (见讨论).
threshold_type
取阈值类型:必须是下者之一
  • CV_THRESH_BINARY,
  • CV_THRESH_BINARY_INV
block_size
用来计算阈值的象素邻域大小: 3, 5, 7, ...
param1
与方法有关的参数。对方法 CV_ADAPTIVE_THRESH_MEAN_C 和 CV_ADAPTIVE_THRESH_GAUSSIAN_C, 它是一个从均值或加权均值提取的常数(见讨论), 尽管它可以是负数。

函数 cvAdaptiveThreshold 将灰度图像变换到二值图像,采用下面公式:

threshold_type=CV_THRESH_BINARY:
dst(x,y) = max_value, if src(x,y)>T(x,y)
           0, otherwise

threshold_type=CV_THRESH_BINARY_INV:
dst(x,y) = 0, if src(x,y)>T(x,y)
           max_value, otherwise

其中 TI 是为每一个象素点单独计算的阈值

对方法 CV_ADAPTIVE_THRESH_MEAN_C,先求出块中的均值,再减掉param1。

对方法 CV_ADAPTIVE_THRESH_GAUSSIAN_C ,先求出块中的加权和(gaussian), 再减掉param1。


实现代码:

/*
* 自适应阈值
*/

#include "cv.h"
#include "highgui.h"
#include "math.h"

void doAdaptThreshold(IplImage* img)
{
	IplImage* Igray = 0;
	IplImage* It = 0;
	IplImage* Iat;
	Igray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	cvCvtColor(img,Igray,CV_RGB2GRAY);
	It = cvCreateImage(cvSize(Igray->width,Igray->height), IPL_DEPTH_8U, 1);
	Iat = cvCreateImage(cvSize(Igray->width, Igray->height), IPL_DEPTH_8U, 1);
	cvThreshold(Igray, It, 150, 255, CV_THRESH_BINARY);
	cvAdaptiveThreshold(Igray, Iat, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 3, 5);

	cvNamedWindow("raw",1);
	cvNamedWindow("Threshold",1);
	cvNamedWindow("Ada", 1);
	cvShowImage("raw", Igray);
	cvShowImage("Threshold", It);
	cvShowImage("Ada", Iat);
	
	cvWaitKey(0);
	cvReleaseImage(&Igray);
	cvReleaseImage(&It);
	cvReleaseImage(&Iat);
	cvDestroyWindow("raw");
	cvDestroyWindow("Threshold");
	cvDestroyWindow("Ada");
}


结果:

第一张图为原图的灰度图

第二张图为二值阈值化

第三张为自适应二值阈值化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值