灰度图像与二值化


问题描述:将彩色图像转换为灰度图像并进行二值化处理

代码如下(示例):

#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}^2S0​2, S12{S_1}^2S1​2分别代表000类和111类中灰度值的方差;
  • M0M_0M0​,M1M_1M1​分别代表000类和111类中灰度值的平均值;

基于上述定义,我们便可以根据下述公式计算出类内方差类间方差,即:

  • 类内方差:Sw2=w0S02+w1S12{S_w}^2=w_0\ {S_0}^2+w_1\ {S_1}^2Sw​2=w0​ S0​2+w1​ S1​2
  • 类间方差: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) ^2Sb​2=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{常数}St​2=Sw​2+Sb​2=常数

根据上述公式,我们可以类内方差类间方差的比值,并用分离度XXX来表示:

X=Sb2Sw2=Sb2St2−Sb2X = \frac{{S_b}^2}{{S_w}^2} = \frac{{S_b}^2}{{S_t}^2 - {S_b}^2} X=Sw​2Sb​2​=St​2−Sb​2Sb​2​

也就是说:
arg⁡max⁡tX=arg⁡max⁡tSb2\arg\max\limits_{t}\ X=\arg\max\limits_{t}\ {S_b}^2 argtmax​ X=argtmax​ Sb​2
换言之,如果使Sb2=w0w1(M0−M1)2{S_b}^2={w_0}\ {w_1}\ (M_0 - M_1)^2Sb​2=w0​ w1​ (M0​−M1​)2最大,就可以得到最好的二值化阈值ththth。

图像处理之灰度图像转换与二值化相关推荐

  1. OpenCV图像处理(17)—— 各种二值化对比

    /*************************************************************************************************** ...

  2. 【OpenCV案例实战分享】关于图像处理的一些基本操作之二值化、图像加噪处理......

    导语

  3. 【转】c#数字图像处理(二)彩色图像灰度化,灰度图像二值化

    转自:https://www.cnblogs.com/dearzhoubi/p/8571652.html 为加快处理速度,在图像处理算法中,往往需要把彩色图像转换为灰度图像,在灰度图像上得到验证的算法 ...

  4. MATLAB图像处理之二值化以及灰度处理

    首先先来明白几个概念: 1.彩色图像(RGB):图像的每个像素点都是由红(R).绿(G).蓝(B)三个分量来表示的,每一个分量一般分别介于0-255之间,当然如果每一个颜色分量用更多的位数去表示的话, ...

  5. 小白入门计算机视觉(二) : 图像基本处理----灰度图和二值化

    文章目录 解剖图像 图像处理基本原理 RGB模型 灰度 二值化 图像失真问题 从本节开始,我就要正式踏上小白的计算机视觉探索之路,先从图像基础学习吧 解剖图像 要学会图像处理首先就得知道图像的结构,平 ...

  6. 使用深度学习解决拍照文档复杂背景二值化问题

    前言 1.在手持拍照设备对文档进行拍照时,很容易出现光线不均.阴影.过暗等,或者有些旧的文档,古籍文档都有虫洞.透背.字迹不清现象,为了方便阅读.打印文档,或者OCR识别,这些干扰都对处理结果有很多不 ...

  7. c#图像灰度化、灰度反转、二值化

    图像灰度化: 将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*2 ...

  8. cv2 inrange灰度图_基于openCV,PIL的深色多背景复杂验证码图像转灰度二值化,并去噪降噪处理分析...

    title: [python]基于openCV,PIL的深色多背景复杂验证码图像转灰度二值化,并去噪降噪处理分析 type: categories copyright: true categories ...

  9. opencv 轮廓放大_基于openCV,PIL的深色多背景复杂验证码图像转灰度二值化,并去噪降噪处理分析...

    title: [python]基于openCV,PIL的深色多背景复杂验证码图像转灰度二值化,并去噪降噪处理分析 type: categories copyright: true categories ...

最新文章

  1. python随机产生10个不同的两位数_python解决两位数加减法快速出题问题
  2. jQuery的Ajax方法实现注册邮箱时用户名查询
  3. UPX命令行压缩、反汇编动画进入、OllyDbg搜索命令功能
  4. 互联网1分钟 |1029
  5. php 从字符中随机挑一个数,php 对中文字符串的处理- 随机取出指定个数的汉字...
  6. shd_config ssh设置(ssh客户端连接服务器断开)
  7. Java实现Huffman哈夫曼树(数组实现)
  8. java无效的源发行版_无效的Java
  9. PixiJS - 基于 WebGL 的超快 HTML5 2D 渲染引擎
  10. [css] 为什么说不提倡用1px的小尺寸图片做背景平铺?
  11. 沟通科技:将引领接入革命第三次浪潮
  12. mysql中exeits用法_MySQL 8 在 Windows 下安装及使用
  13. python网球比赛模拟_【Python】以模块化做比赛模拟
  14. .Net 获取IP 地址和计算机名(本地网)
  15. html5有哪些优点,HTML5真正的优势优点有什么?
  16. 2019-数学建模美赛-B题翻译
  17. 抱薪者说 | 廿七喜得子老王为名忧,论坛聚英豪树鑫拔头筹
  18. 读论文Beyond Part Models Person Retrieval with Refined Part Pooling
  19. (C语言)有一个已排好序的数组,要求输入一个数字后,按原来的排序规律将它插入数组
  20. android 回编译失败,Androidkiller 回编译失败

热门文章

  1. 网易2020校招笔试-c++开发工程师
  2. 实现点击弹框外关闭弹框功能
  3. 使用virtualenv搭建一个干净的python开发环境
  4. 同一个世界游戏 算法破解
  5. MATLAB R2016a 安装教程
  6. 《ChatGPT Prompt Engineering for Developers》课程-提示词原则
  7. 论文笔记(六):A VR Teleoperation Suite with Manipulation Assist
  8. 互联网大佬杨浩涌的创业历程,尽管遭遇合并但依旧辉煌
  9. 7-3 学生顺序表的建立
  10. 贝塞尔曲线(Bezier Curve)原理、公式推导及matlab代码实现