Opencv二值化是将图像使用黑和白两种值表示的方法(灰度值为0或255),也就是将整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的阈值选取而获得仍然可以反映图像整体和局部特征的二值化图像。在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样子有利于在对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单,而且数据的处理和压缩量小。为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。
如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用阈值法就可以得到比较的分割效果。如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阈值选取技术来分割该图像。动态调节阈值实现图像的二值化可动态观察其分割图像的具体结果。
这里我们将灰度的阈值设置为 128 来进行二值化,即:
y = { 0 (if y < 128)
255 (else)
Python 实现:
import cv2
import numpy as np
# Read image
img = cv2.imread("imori.jpg").astype(np.float)
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# Grayscale
out = 0.2126 * r + 0.7152 * g + 0.0722 * b
out = out.astype(np.uint8)
# Binarization
th = 128
out[out < th] = 0
out[out >= th] = 255
# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
C++ 实现:
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
int main(int argc, const char* argv[]){
cv::Mat img = cv::imread("imori.jpg", cv::IMREAD_COLOR);
int width = img.rows;
int height = img.cols;
int th = 128;
cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);
for (int j=0; j<height; j++){
for (int i=0; i<width; i++){
uchar val = (int)((float)img.at<cv::Vec3b>(j,i)[0] * 0.0722 + \
(float)img.at<cv::Vec3b>(j,i)[1] * 0.7152 + \
(float)img.at<cv::Vec3b>(j,i)[2] * 0.2126);
if (val < th){
val = 0;
} else {
val = 255;
}
out.at<uchar>(j,i) = val;
}
}
//cv::imwrite("out.jpg", out);
cv::imshow("answer", out);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
输入:
输出: