图像验证码识别(四)——灰度化和二值化
2016-03-01 14:34
417 查看
一、灰度化
灰度化应用很广,而且也比较简单。灰度图就是将白与黑中间的颜色等分为若干等级,绝大多数位256阶。在RGB模型种,黑色(R=G=B=0)与白色(R=G=B=255),那么256阶的灰度划分就是R=G=B=i,其中i取0到255.
从前面可以知道,OpenCV读取图片之后图像的颜色数据矩阵默认是3通道的,也就是RGB模型,所以每个pixel都有3个分量,分别代表r,g和b的值。因此将三个分量值都改为同一个灰度值,图片就实现灰度化。
灰度化的方法一般有以下几种:
1. 分量法
在rgb三个分量种按照需求选取一个分量作为灰度值
2. 最大值
选取rgb的最大值作为该pixel的灰度值
3. 平均值
g[i,j] = (r[i,j] + g[i,j] + b[i,j]) / 3,取rgb的平均值作为灰度值
4. 加权变换
由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像。
g[i,j] = 0.3*r[i,j] + 0.59*g[i,j] + 0.11*b[i,j]
而OpenCV提供了灰度化的API,这里就直接调用了,采用的是加权变换的方法.
[cpp] view
plain copy
void Image::toGray()
{
Mat iGray;
if (getChannel() == 3)
{
std::cout << "width : " << getWidth() << std::endl;
std::cout << "height: " << getHeight() << std::endl;
cvtColor(m_Mat,iGray,COLOR_BGR2GRAY);
m_Mat = iGray;
std::cout << "The file has been converted to gray map successfully" << std::endl;
std::cout << "***********************************" << std::endl;
}
else
{
std::cout << "the image file is not RGB file!" << std::endl;
}
}
二、二值化
二值化故名思议,就是整个图像所有像素只有两个值可以选择,一个是黑(灰度为0),一个是白(灰度为255)。二值化的好处就是将图片上的有用信息和无用信息区分开来,比如二值化之后的验证码图片,验证码像素为黑色,背景和干扰点为白色,这样后面对验证码像素处理的时候就会很方便。
常见的二值化方法为固定阀值和自适应阀值,固定阀值就是制定一个固定的数值作为分界点,大于这个阀值的像素就设为255,小于该阀值就设为0,这种方法简单粗暴,但是效果不一定好.另外就是自适应阀值,每次根据图片的灰度情况找合适的阀值。自适应阀值的方法有很多,这里采用了一种类似K均值的方法,就是先选择一个值作为阀值,统计大于这个阀值的所有像素的灰度平均值和小于这个阀值的所有像素的灰度平均值,再求这两个值的平均值作为新的阀值。重复上面的计算,直到每次更新阀值后,大于该阀值和小于该阀值的像素数目不变为止。
代码如下:
[cpp] view
plain copy
//k-mean method to find a threshold by itself
void Image::Binarization()
{
int i,j,nWidth,nHeight;
int nBack_count,nData_count;
int nBack_sum,nData_sum;
uchar ucThre,ucThre_new;
int nValue;
nWidth = getWidth();
nHeight = getHeight();
//initial the threshold
ucThre = 0;
ucThre_new = 127;
std::cout << "Initial Threshold is :" << (int)ucThre_new << std::endl;
std::cout << "***********************************" << std::endl;
while(ucThre != ucThre_new) {
nBack_sum = nData_sum = 0;
nBack_count = nData_count = 0;
for (j = 0; j < nHeight; ++j)
{
for (i = 0; i < nWidth; ++i)
{
nValue = getPixel(i,j);
if (nValue > ucThre_new)
{
nBack_sum += nValue;
nBack_count++;
}
else {
nData_sum += nValue;
nData_count++;
}
}
}// end for i
nBack_sum = nBack_sum / nBack_count;
nData_sum = nData_sum / nData_count;
ucThre = ucThre_new;
ucThre_new = (nBack_sum + nData_sum) / 2;
}// end while
std::cout << "After Binarization threshold is :" << (int)ucThre_new << std::endl;
int nBlack = 0;
int nWhite = 0;
for (j = 0; j < nHeight; ++j)
{
for (i = 0; i < nWidth; ++i)
{
nValue = getPixel(i,j);
if (nValue > ucThre_new)
{
setPixel(i,j,(uchar)WHITE);
nWhite++;
}
else {
setPixel(i,j,BLACK);
nBlack++;
}
}
}
//backgroud is black,swap black and white
if (nBlack > nWhite)
{
for (j = 0; j < nHeight; ++j)
for (i = 0; i < nWidth; ++i)
{
nValue = getPixel(i,j);
if ( !nValue )
setPixel(i,j,(uchar)WHITE);
else
setPixel(i,j,BLACK);
}
}
std::cout << "Binarization finished!" << std::endl;
}
这里最后在二值化之后有一个反色的操作,在项目种规定了白色是背景,黑色是数据,但是有时候如果验证码图片的色彩比较重,最后会导致背景为黑色,数据为白色,所以这里进行了一个判断,由于绝大多数情况下,验证码的大部分像素还是充当背景的,所以如果最后统计的黑色像素点数目大于白色的,就将所有像素的二值取反。
灰度化应用很广,而且也比较简单。灰度图就是将白与黑中间的颜色等分为若干等级,绝大多数位256阶。在RGB模型种,黑色(R=G=B=0)与白色(R=G=B=255),那么256阶的灰度划分就是R=G=B=i,其中i取0到255.
从前面可以知道,OpenCV读取图片之后图像的颜色数据矩阵默认是3通道的,也就是RGB模型,所以每个pixel都有3个分量,分别代表r,g和b的值。因此将三个分量值都改为同一个灰度值,图片就实现灰度化。
灰度化的方法一般有以下几种:
1. 分量法
在rgb三个分量种按照需求选取一个分量作为灰度值
2. 最大值
选取rgb的最大值作为该pixel的灰度值
3. 平均值
g[i,j] = (r[i,j] + g[i,j] + b[i,j]) / 3,取rgb的平均值作为灰度值
4. 加权变换
由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像。
g[i,j] = 0.3*r[i,j] + 0.59*g[i,j] + 0.11*b[i,j]
而OpenCV提供了灰度化的API,这里就直接调用了,采用的是加权变换的方法.
[cpp] view
plain copy
void Image::toGray()
{
Mat iGray;
if (getChannel() == 3)
{
std::cout << "width : " << getWidth() << std::endl;
std::cout << "height: " << getHeight() << std::endl;
cvtColor(m_Mat,iGray,COLOR_BGR2GRAY);
m_Mat = iGray;
std::cout << "The file has been converted to gray map successfully" << std::endl;
std::cout << "***********************************" << std::endl;
}
else
{
std::cout << "the image file is not RGB file!" << std::endl;
}
}
二、二值化
二值化故名思议,就是整个图像所有像素只有两个值可以选择,一个是黑(灰度为0),一个是白(灰度为255)。二值化的好处就是将图片上的有用信息和无用信息区分开来,比如二值化之后的验证码图片,验证码像素为黑色,背景和干扰点为白色,这样后面对验证码像素处理的时候就会很方便。
常见的二值化方法为固定阀值和自适应阀值,固定阀值就是制定一个固定的数值作为分界点,大于这个阀值的像素就设为255,小于该阀值就设为0,这种方法简单粗暴,但是效果不一定好.另外就是自适应阀值,每次根据图片的灰度情况找合适的阀值。自适应阀值的方法有很多,这里采用了一种类似K均值的方法,就是先选择一个值作为阀值,统计大于这个阀值的所有像素的灰度平均值和小于这个阀值的所有像素的灰度平均值,再求这两个值的平均值作为新的阀值。重复上面的计算,直到每次更新阀值后,大于该阀值和小于该阀值的像素数目不变为止。
代码如下:
[cpp] view
plain copy
//k-mean method to find a threshold by itself
void Image::Binarization()
{
int i,j,nWidth,nHeight;
int nBack_count,nData_count;
int nBack_sum,nData_sum;
uchar ucThre,ucThre_new;
int nValue;
nWidth = getWidth();
nHeight = getHeight();
//initial the threshold
ucThre = 0;
ucThre_new = 127;
std::cout << "Initial Threshold is :" << (int)ucThre_new << std::endl;
std::cout << "***********************************" << std::endl;
while(ucThre != ucThre_new) {
nBack_sum = nData_sum = 0;
nBack_count = nData_count = 0;
for (j = 0; j < nHeight; ++j)
{
for (i = 0; i < nWidth; ++i)
{
nValue = getPixel(i,j);
if (nValue > ucThre_new)
{
nBack_sum += nValue;
nBack_count++;
}
else {
nData_sum += nValue;
nData_count++;
}
}
}// end for i
nBack_sum = nBack_sum / nBack_count;
nData_sum = nData_sum / nData_count;
ucThre = ucThre_new;
ucThre_new = (nBack_sum + nData_sum) / 2;
}// end while
std::cout << "After Binarization threshold is :" << (int)ucThre_new << std::endl;
int nBlack = 0;
int nWhite = 0;
for (j = 0; j < nHeight; ++j)
{
for (i = 0; i < nWidth; ++i)
{
nValue = getPixel(i,j);
if (nValue > ucThre_new)
{
setPixel(i,j,(uchar)WHITE);
nWhite++;
}
else {
setPixel(i,j,BLACK);
nBlack++;
}
}
}
//backgroud is black,swap black and white
if (nBlack > nWhite)
{
for (j = 0; j < nHeight; ++j)
for (i = 0; i < nWidth; ++i)
{
nValue = getPixel(i,j);
if ( !nValue )
setPixel(i,j,(uchar)WHITE);
else
setPixel(i,j,BLACK);
}
}
std::cout << "Binarization finished!" << std::endl;
}
这里最后在二值化之后有一个反色的操作,在项目种规定了白色是背景,黑色是数据,但是有时候如果验证码图片的色彩比较重,最后会导致背景为黑色,数据为白色,所以这里进行了一个判断,由于绝大多数情况下,验证码的大部分像素还是充当背景的,所以如果最后统计的黑色像素点数目大于白色的,就将所有像素的二值取反。
相关文章推荐
- C#实现把彩色图片灰度化代码分享
- C#数字图象处理之图像灰度化方法
- c#实现图片二值化例子(黑白效果)
- C#数字图像处理之图像二值化(彩色变黑白)的方法
- python中使用OpenCV进行人脸检测的例子
- opencv 做人脸识别 opencv 人脸匹配分析
- 使用opencv拉伸图像扩大分辨率示例
- c#中实现图片灰度化技术详解
- Perl使用Tesseract-OCR实现验证码识别教程
- 基于C++实现kinect+opencv 获取深度及彩色数据
- OpenCV 2.4.3 C++ 平滑处理分析
- php制作的简单验证码识别代码
- C#实现的简单验证码识别实例
- Python中使用OpenCV库来进行简单的气象学遥感影像计算
- 利用Python和OpenCV库将URL转换为OpenCV格式的方法
- python结合opencv实现人脸检测与跟踪
- Python实现的百度站长自动URL提交小工具
- Python环境搭建之OpenCV的步骤方法
- Python实现OpenCV的安装与使用示例
- 在树莓派2或树莓派B+上安装Python和OpenCV的教程