完成许多处理步骤之后,通常希望对图像中的像素做出最后的决策,或直接剔除一些低于或高于一定值的像素。在OpenCV中,函数cv::threshold()可以完成这些任务。其基本思想是,给定一个数组和一个阈值,然后根据数组中的每个元素的值是低于还是高于阈值而进行一些处理。
double cv::threshold(
cv::InputArray src, // Input image
cv::OutputArray dst, // Result image
double thresh, // Threshold value
double maxValue, // Max value for upward operations
int thresholdType // Threshold type to use
);
如下图所示,每个与之类型对应于一个特定的比较操作,该比较操作在源图像第 i 个像素( src i )和阈值之间进行。根据源图像的像素和阈值之间的关系,目标图像的像素dst i可能被设置为0, src i 或者最大值maxValue。
cv::threshold()中阈值类型选项和对应的操作
下图有助于我们理解每一个阈值类型的确切操作
我们来看一个简单例子。我们对图像中的三个通道就和,然后在值为100处,对结果图像进行截断。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
void sum_rgb( const cv::Mat& src, cv::Mat& dst ) {
// Split image onto the color planes.
//
vector< cv::Mat> planes;
cv::split(src, planes);
cv::Mat b = planes[0], g = planes[1], r = planes[2], s;
// Add equally weighted rgb values.
//
cv::addWeighted( r, 1./3., g, 1./3., 0.0, s );
cv::addWeighted( s, 1., b, 1./3., 0.0, s );
// Truncate values above 100.
//
cv::threshold( s, dst, 100, 100, cv::THRESH_TRUNC );
}
void help() {
cout << "Call: ./ch10_ex10_1 faceScene.jpg" << endl;
cout << "Shows use of alpha blending (addWeighted) and threshold" << endl;
}
int main(int argc, char** argv) {
help();
if(argc < 2) { cout << "specify input image" << endl; return -1; }
// Load the image from the given file name.
//
cv::Mat src = cv::imread( argv[1] ), dst;
if( src.empty() ) { cout << "can not load " << argv[1] << endl; return -1; }
sum_rgb( src, dst);
// Create a named window with the name of the file and
// show the image in the window
//
cv::imshow( argv[1], dst );
// Idle until the user hits any key.
//
cv::waitKey(0);
return 0;
}
这里包含几个重要的思想。第一,我们通常不会对8位数组进行加法运算,因为较高的位可能会溢出。取而代之,我们使用加权加法算法(cv::addWeighted())对三个通道求和;然后对结果以100为阈值进行截断处理然后返回。我们在例子中使用了s的浮点临时图像。我们可以用下一个例子中所示的代码代替。请注意,cv :: accumulate()可以将8位整数图像类型累加到浮点图像中。
void sum_rgb( const cv::Mat& src, cv::Mat& dst ) {
// Split image onto the color planes.
//
vector<cv::Mat> planes;
cv::split(src, planes);
cv::Mat b = planes[0], g = planes[1], r = planes[2];
// Accumulate separate planes, combine and threshold.
//
cv::Mat s = cv::Mat::zeros(b.size(), CV_32F);
cv::accumulate(b, s);
cv::accumulate(g, s);
cv::accumulate(r, s);
// Truncate values above 100 and rescale into dst.
//
cv::threshold( s, s, 100, 100, cv::THRESH_TRUNC );
s.convertTo(dst, b.type());
}