图像处理之灰度图像转换与二值化
灰度图像与二值化
问题描述:将彩色图像转换为灰度图像并进行二值化处理
代码如下(示例):
#include <opencv2/opencv.hpp>cv::Mat BGR2GRAY(cv::Mat img)
{int width = img.cols;int height = img.rows;// CV_8UC1代表单通道的8bit array数组cv::Mat new_image = cv::Mat::zeros(height, width, CV_8UC1);for (int i = 0; i < height; ++i){for (int j = 0; j < width; ++j){// 转换公式 img_gray = 0.2126 * R + 0.7152 * G + 0.0722 * B;// 需要注意图像格式输出的是整数new_image.at<uchar>(i, j) = 0.2126 * (float)img.at<cv::Vec3b>(i, j)[2]\+ 0.7152 * (float)img.at<cv::Vec3b>(i, j)[1]\+ 0.0722 * (float)img.at<cv::Vec3b>(i, j)[0];}}return new_image;
}cv::Mat Binarize(cv::Mat img, int thres)
{int width = img.cols;int height = img.rows;cv::Mat new_image = cv::Mat::zeros(height, width, CV_8UC1);for (int i = 0; i < height; ++i){for (int j = 0; j < width; ++j){if (img.at<uchar>(i, j) > thres){new_image.at<uchar>(i, j) = 255;}else{img.at<uchar>(i, j) = 0;}}}return new_image;
}cv::Mat Binarize_Otsu(cv::Mat img)
{int width = img.cols;int height = img.rows;double count0 = 0, count1 = 0;double sum_val0 = 0, sum_val1 = 0;double sigma_max = 0, sigma = 0;int thres = 0;int val = 0;for (int th = 0; th < 255; ++th){for (int i = 0; i < height; ++i){count0 = 0; // 每次循环重置参数count1 = 0;sum_val0 = 0;sum_val1 = 0;for (int j = 0; j < width; ++j){val = (int)img.at<uchar>(i, j);if (val < th){count0++;sum_val0 += val;}else{count1++;sum_val1 += val;}}}sum_val0 /= count0;sum_val1 /= count1;count0 /= (height * width);count1 /= (height * width);sigma = count0 * count1 * pow((sum_val0 - sum_val1), 2);if (sigma > sigma_max){sigma_max = sigma;thres = th;}}std::cout << "threshold: " << thres << std::endl;cv::Mat new_image = cv::Mat::zeros(height, width, CV_8UC1);for (int i = 0; i < height; ++i){for (int j = 0; j < width; ++j){if (img.at<uchar>(i, j) > thres){new_image.at<uchar>(i, j) = 255;}else{img.at<uchar>(i, j) = 0;}}}return new_image;
}int main()
{cv::Mat img = cv::imread("../Neopolitan.png", cv::IMREAD_COLOR);// BGR2GRAYcv::Mat gray_image = BGR2GRAY(img);cv::Mat new_image = Binarize(gray_image, 128);// cv::Mat new_image = Binarize_Otsu(gray_image); // 大津二值化cv::imwrite("../1-10/Neopolitan2.png", gray_image);cv::imwrite("../1-10/Neopolitan3.png", new_image);// cv::imwrite("../1-10/Neopolitan4.png", new_image);cv::waitKey(0);cv::destroyAllWindows();return 0;
}
输入图像 (Neopolitan.png) | 灰度图像 (Neopolitan2.png) | 二值化图像 (Neopolitan3.png) | 大津二值化图像 (Neopolitan4.png) |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Vec3b
Vec3b
可以看作是vector<uchar, 3>
,简单而言就是一个uchar类型的,长度为3的vector向量。
由于在OpenCV中,使用imread读取到的Mat图像数据,都是用uchar类型的数据存储,对于RGB三通道的图像,每个点的数据都是一个Vec3b类型的数据。使用at定位方法如下:
img.at<Vec3b>(row, col)[0] = 255; // 这是指修改B通道数据
img.at<Vec3b>(row, col)[1] = 255; // 这是指修改G通道数据
img.at<Vec3b>(row, col)[2] = 255; // 这是指修改R通道数据
大津二值化
大津算法,也被称作最大类间方差法,是一种可以自动确定二值化中阈值的算法。即,使得类内方差和类间方差的比值最大的阈值即为大津二值化阈值。
我们可以通过以下的参数来计算大津二值化阈值:
- 我们可以通过阈值ththth将图像灰度值分为两类,小于阈值ththth的类记作000,大于阈值ththth的类记作111;
- w0w_0w0和w1w_1w1分别代表000类和111类中的灰度值数目占总灰度值数目(也即像素个数)的比率(满足w0+w1=1w_0+w_1=1w0+w1=1);
- S02{S_0}^2S02, S12{S_1}^2S12分别代表000类和111类中灰度值的方差;
- M0M_0M0,M1M_1M1分别代表000类和111类中灰度值的平均值;
基于上述定义,我们便可以根据下述公式计算出类内方差和类间方差,即:
- 类内方差:Sw2=w0S02+w1S12{S_w}^2=w_0\ {S_0}^2+w_1\ {S_1}^2Sw2=w0 S02+w1 S12
- 类间方差:Sb2=w0(M0−Mt)2+w1(M1−Mt)2=w0w1(M0−M1)2{S_b}^2 = w_0 \ (M_0 - M_t)^2 + w_1\ (M_1 - M_t)^2 = w_0\ w_1\ (M_0 - M_1) ^2Sb2=w0 (M0−Mt)2+w1 (M1−Mt)2=w0 w1 (M0−M1)2
- 图像所有灰度值的方差:St2=Sw2+Sb2=常数{S_t}^2 = {S_w}^2 + {S_b}^2 = \text{常数}St2=Sw2+Sb2=常数
根据上述公式,我们可以类内方差和类间方差的比值,并用分离度XXX来表示:
X=Sb2Sw2=Sb2St2−Sb2X = \frac{{S_b}^2}{{S_w}^2} = \frac{{S_b}^2}{{S_t}^2 - {S_b}^2} X=Sw2Sb2=St2−Sb2Sb2
也就是说:
argmaxtX=argmaxtSb2\arg\max\limits_{t}\ X=\arg\max\limits_{t}\ {S_b}^2 argtmax X=argtmax Sb2
换言之,如果使Sb2=w0w1(M0−M1)2{S_b}^2={w_0}\ {w_1}\ (M_0 - M_1)^2Sb2=w0 w1 (M0−M1)2最大,就可以得到最好的二值化阈值ththth。
图像处理之灰度图像转换与二值化相关推荐
- OpenCV图像处理(17)—— 各种二值化对比
/*************************************************************************************************** ...
- 【OpenCV案例实战分享】关于图像处理的一些基本操作之二值化、图像加噪处理......
导语
- 【转】c#数字图像处理(二)彩色图像灰度化,灰度图像二值化
转自:https://www.cnblogs.com/dearzhoubi/p/8571652.html 为加快处理速度,在图像处理算法中,往往需要把彩色图像转换为灰度图像,在灰度图像上得到验证的算法 ...
- MATLAB图像处理之二值化以及灰度处理
首先先来明白几个概念: 1.彩色图像(RGB):图像的每个像素点都是由红(R).绿(G).蓝(B)三个分量来表示的,每一个分量一般分别介于0-255之间,当然如果每一个颜色分量用更多的位数去表示的话, ...
- 小白入门计算机视觉(二) : 图像基本处理----灰度图和二值化
文章目录 解剖图像 图像处理基本原理 RGB模型 灰度 二值化 图像失真问题 从本节开始,我就要正式踏上小白的计算机视觉探索之路,先从图像基础学习吧 解剖图像 要学会图像处理首先就得知道图像的结构,平 ...
- 使用深度学习解决拍照文档复杂背景二值化问题
前言 1.在手持拍照设备对文档进行拍照时,很容易出现光线不均.阴影.过暗等,或者有些旧的文档,古籍文档都有虫洞.透背.字迹不清现象,为了方便阅读.打印文档,或者OCR识别,这些干扰都对处理结果有很多不 ...
- c#图像灰度化、灰度反转、二值化
图像灰度化: 将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*2 ...
- cv2 inrange灰度图_基于openCV,PIL的深色多背景复杂验证码图像转灰度二值化,并去噪降噪处理分析...
title: [python]基于openCV,PIL的深色多背景复杂验证码图像转灰度二值化,并去噪降噪处理分析 type: categories copyright: true categories ...
- opencv 轮廓放大_基于openCV,PIL的深色多背景复杂验证码图像转灰度二值化,并去噪降噪处理分析...
title: [python]基于openCV,PIL的深色多背景复杂验证码图像转灰度二值化,并去噪降噪处理分析 type: categories copyright: true categories ...
最新文章
- python随机产生10个不同的两位数_python解决两位数加减法快速出题问题
- jQuery的Ajax方法实现注册邮箱时用户名查询
- UPX命令行压缩、反汇编动画进入、OllyDbg搜索命令功能
- 互联网1分钟 |1029
- php 从字符中随机挑一个数,php 对中文字符串的处理- 随机取出指定个数的汉字...
- shd_config ssh设置(ssh客户端连接服务器断开)
- Java实现Huffman哈夫曼树(数组实现)
- java无效的源发行版_无效的Java
- PixiJS - 基于 WebGL 的超快 HTML5 2D 渲染引擎
- [css] 为什么说不提倡用1px的小尺寸图片做背景平铺?
- 沟通科技:将引领接入革命第三次浪潮
- mysql中exeits用法_MySQL 8 在 Windows 下安装及使用
- python网球比赛模拟_【Python】以模块化做比赛模拟
- .Net 获取IP 地址和计算机名(本地网)
- html5有哪些优点,HTML5真正的优势优点有什么?
- 2019-数学建模美赛-B题翻译
- 抱薪者说 | 廿七喜得子老王为名忧,论坛聚英豪树鑫拔头筹
- 读论文Beyond Part Models Person Retrieval with Refined Part Pooling
- (C语言)有一个已排好序的数组,要求输入一个数字后,按原来的排序规律将它插入数组
- android 回编译失败,Androidkiller 回编译失败