基本思想:给定一个数组和一个阈值,然后根据数组中的每个元素的值是低于还是高于阈值而进行一些处理
/* Applies fixed-level threshold to grayscale image.
This is a basic operation applied before retrieving contours */
CVAPI(double) cvThreshold( const CvArr* src, CvArr* dst,
double threshold, double max_value,
int threshold_type );
如下表所示,每个阈值类型对应于一个特定的比较操作,该比较操作在源图像第i个像素(srci)和阈值(表中表示为T)之间进行。根据源图像的像素和阈值之间的关系,目标图像的像素dsti可能被设置为0,srci或max_value(表中表示为M)
阈值类型 | 操作 |
CV_THRESH_BINARY | dsti=(srci > T)?M:0 |
CV_THRESH_BINARY_INV | dsti=(srci>T)?0:M |
CV_THRESH_TRUNC | dsti=(srci>T)?M:srci |
CV_THRESH_TOZERO_INV | dsti=(srci>T)?0:srci |
CV_THRESH_TOZERO | dsti=(srci>T)?srci:0 |
1.cvThreshold()函数只能处理8位或浮点灰度图像
2.目标图像必须与源图像的类型一致,或者为8位图像
3.源图像和目标图像可以是同一图像
程序:对图像中三个通道求和,然后在值为100处对结果图像进行截断
#include "threshold.h"
//对图像中的三个通道求和,然后在值为100处对结果图像进行截断
void sum_rgb(IplImage *src, IplImage *dst)
{
//Allocate individual image planes
IplImage *r=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage *g=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage *b=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
//Split image onto the color plane
cvSplit(src, r, g, b, NULL);
//Temporary storage
IplImage *s=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
//Add equally weighted rgb values
cvAddWeighted(r, 1./3., g, 1./3., 0.0, s);
cvAddWeighted(s, 2./3., b, 1./3., 0.0, s);
//Truncate values above 100.
cvThreshold(s, dst, 100, 100, CV_THRESH_TRUNC);
cvReleaseImage(&r);
cvReleaseImage(&g);
cvReleaseImage(&b);
cvReleaseImage(&s);
}
int main(void)
{
cvNamedWindow("Threshold");
//Load the image from the given file name.
IplImage *src=cvLoadImage("lena.jpg");
IplImage *dst=cvCreateImage(cvGetSize(src), src->depth, 1);
if (src == NULL || dst == NULL)
exit(0);
sum_rgb(src, dst);
//Show the image in the named window
cvShowImage("Threshold", dst);
//Idle until the user hits the "Esc" key
while (true)
if (cvWaitKey(10) == 27)
break;
//Clean up and don't be piggies
cvDestroyWindow("Threshold");
cvReleaseImage(&src);
cvReleaseImage(&dst);
}
################################################
/* Applies adaptive threshold to grayscale image.
The two parameters for methods CV_ADAPTIVE_THRESH_MEAN_C and
CV_ADAPTIVE_THRESH_GAUSSIAN_C are:
neighborhood size (3, 5, 7 etc.),
and a constant subtracted from mean (...,-3,-2,-1,0,1,2,3,...) */
CVAPI(void) cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value,
int adaptive_method CV_DEFAULT(CV_ADAPTIVE_THRESH_MEAN_C),
int threshold_type CV_DEFAULT(CV_THRESH_BINARY),
int block_size CV_DEFAULT(3),
double param1 CV_DEFAULT(5));
这是一种改进了的阈值技术,其中阈值本身是一个变量
cvAdaptiveThreshold()有两种不同的自适应阈值方法,可以用参数adaptive_method进行设置。在两种情况下,自适应阈值T(x, y)在每个像素点都不同。通过计算像素点周围的bxb区域的加权平均,然后减去一个常熟来得到自适应阈值,b由参数block_size指定,常数由param1制定。如果使用CV_ADAPTIVE_THRESH_MEAN_C方法,那么对区域的所有像素平均加权。如果使用了CV_ADAPTIVE_THRESH_GAUSSIAN_C方法,那么区域中的(x, y)周围的像素根据高斯函数按照它们离中心点的距离进行加权计算。
参数threshold_type和cvThreshold()的参数threshold_type是一样的
note:本函数要求源图像和目标图像不能使用同一图像
void adaptiveThre(void)
{
//比较cvThreshold()函数和cvAdaptiveThreshold函数
IplImage *src, *dst1, *dst2, *dst3;
src=cvLoadImage("left04.jpg", CV_LOAD_IMAGE_GRAYSCALE);
dst1=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
dst2=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
dst3=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
if (src == NULL || dst1 == NULL || dst2 == NULL || dst3 == NULL)
exit(0);
cvThreshold(src, dst1, 100, 255, CV_THRESH_BINARY);
cvAdaptiveThreshold(src, dst2, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 3, 5);
cvAdaptiveThreshold(src, dst3, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 3, 5);
cvNamedWindow("src");
cvNamedWindow("dst1");
cvNamedWindow("dst2");
cvNamedWindow("dst3");
cvShowImage("src", src);
cvShowImage("dst1", dst1);
cvShowImage("dst2", dst2);
cvShowImage("dst3", dst3);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&dst1);
cvReleaseImage(&dst2);
cvReleaseImage(&dst3);
cvDestroyAllWindows();
}