阈值化操作原理是给定一个数组和阈值,对于数组中每个值,根据其高于或低于这个阈值做出响应的处理。也可以把阈值化理解成一个用axa的核进行卷积,对每个像素进行一次非线性操作。
1. 二值化阈值 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个源像素和阈值threshold之间的比较运算方式。根据源像素和阈值之间的关系,目标像素dst可以被赋值为0、src_i或给定的最大值maxValue。返回值阈值
参数thresholdType的可选项:
阈值类型 | 操作 | 说明 |
cv::THRESH_BINARY | DST[i] = (SRC[i] > thresh) ? MAXVALUE : 0 | 二值化 |
cv::THRESH_BINARY_INV | DST[i] = (SRC[i] > thresh) ? 0 : MAXVALUE | 反二值化 |
cv::THRESH_TRUNC | DST[i] = (SRC[i] > thresh) ? THRESH : SRC[i] | 截断,不超过阈值 |
cv::THRESH_TOZERO | DST[i] = (SRC[i] > thresh) ? SRC[i] : 0 | 置0阈操作 |
cv::THRESH_TOZERO_INV | DST[i] = (SRC[i] > thresh) ? 0 : SRC[i] | 反置0阈操作 |
2. 获取最优阈值的算法—Otsu算法
cv::threshold()函数也可以自动决定最优的阈值,需要设置参数type=cv::THRESH_OTSU。
当设置cv::THRESH_OTSU时,阈值设置为0时,函数会返回计算得到的最佳阈值。
Otsu算法是遍历所有可能的阈值,然后对每个阈值结果的两类像素计算方差σ²(即低于阈值核高于阈值的两类像素)。Otsu算法计算方差使下列表达式最小:
和
是根据两类像素的数量计算得到的权值,
和
表示两类像素的方差。
Otsu算法需要遍历所有可能的阈值,相对来说效率不是很高。
3. 自适应阈值 cv::adaptiveThreshold()
自适应阈值在整个过程中自动产生变化。在OpenCv中,函数cv::adaptiveThreshold()实现这种方法。函数原型声明:
void cv::adaptiveThreshold(
cv::InputArray src, // input image
cv::OutputArray dst, // result image
double maxValue, // max value for upward operations
int adaptiveMethod, // mean or Gaussian
int thresholdType, // threshold type to use
int blockSize, // block size
double C // constant
);
cv::adaptiveShold()函数根据adaptiveMethos参数的设置,允许两种不同的自适应阈值方法。这两个方法都是逐个像素地去计算自适应阈值T(x,y),方法是通过计算每个像素位置周围的bxb区域的加权平均值然后减去常数C,其中b由blockSize给定(blockSize一般为奇数),不同的是,
- 如果选择的均值方法是cv::ADAPTIVE_THRESH_MEAN_C,那么均值时取得权值是相等的;
- 如果选择的均值方法是cv::ADAPTIVE_THRESH_GAUSSIAN_C,(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到。
参数thresholdType只支持cv::THRESH_BINARY和cv::THRESH_BINARY_INV。
当图像中出现较大的明暗差异时,自适应阈值非常有效。cv::adaptiveThreshold()函数仅处理单通道8位或浮点图像,并且要求源图像和目标图像不同。
使用示例:
if (argc != 7){
std::cout << "Usage: " << argv[0] << " fixed_threshold invert(0=off|1=on)"
"adaptive_type(0=mean|1=gaussian) block_size offset image\n"
"Example: " << " 100 1 0 15 10 fruits.jpg\n";
return;
}
// command line
double fixed_threshold = (double)atof(argv[1]);
int threshold_type = atoi(argv[2]) ? cv::THRESH_BINARY : cv::THRESH_BINARY_INV;
int adaptive_method = atoi(argv[3]) ? cv::ADAPTIVE_THRESH_MEAN_C : cv::ADAPTIVE_THRESH_GAUSSIAN_C;
int block_size = atoi(argv[4]);
double offset = (double)atof(argv[5]);
cv::Mat Igray = cv::imread(argv[6], CV_LOAD_IMAGE_GRAYSCALE);
if (Igray.empty()){
std::cout << "can not load" << argv[6] << std::endl;
return;
}
cv::Mat It, Iat;
double fThresh = cv::threshold(Igray, It, fixed_threshold, 255, threshold_type); // 输入图片 输出二值化图片 阈值 最大值 阈值类型
cv::adaptiveThreshold(
Igray, // 输入图片
Iat, // 输出图片
255, // 最大值
adaptive_method, //自适应阈值算法(均值或高斯均值 cv::ADAPTIVE_THRESH_MEAN_C 或cv::ADAPTIVE_THRESH_GAUSSIAN_C
threshold_type, // 阈值类型只支持二值化或反二值化
block_size, // 核 blockSize x blockSize区域计算
offset); // 减去常量 offset
cv::imshow("raw", Igray);
cv::imshow("threshold", It);
cv::imshow("adaptive_threshold", Iat);
cv::waitKey(0);
使用的参数为 15 1 1 71 15 E:\\right14.jpg 表示cv::thresh()函数使用的阈值为15,使用的阈值化类型为二值化,使用的自适应阈值类型是cv::ADAPTIVE_THRESH_MEAN_C,自适应阈值时计算的核是71 x 71,减去的常量值是15。显示结果为:
原图 二值化 自适应阈值
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/46153.html