0


利用OpenCV把一幅彩色图像转换成灰度图

图像灰度化的目的是为了简化矩阵,提高运算速度。

彩色图像中的每个像素颜色由R、G、B三个分量来决定,而每个分量的取值范围都在0-255之间,这样对计算机来说,彩色图像的一个像素点就会有256256256=16777216种颜色的变化范围!

而灰度图像是R、G、B分量相同的一种特殊彩色图像,对计算机来说,一个像素点的变化范围只有0-255这256种。

假设我们现在有一幅彩色图像,但是我们现在想得到它的灰度图,应该怎么做呢?

Opencv自带了这种转换函数,

我们可以在用imread()函数读取时设置第二个参数为0,就可以直接得到彩色图像的灰度图;

Mat src0 = imread("C:\\Users\\32498\\Pictures\\16.png",0);

也可以先把彩色图像读进来,然后使用cvtColor函数进行转换得到它的灰度图。

Mat src = imread("C:\\Users\\32498\\Pictures\\16.png");
cvtColor(src, cvt_gray_image,COLOR_BGR2GRAY);

也可以使用心理学公式GRAY=0.299R+0.587G+0.114*B自己编写一个转换函数,其中的加权系数是根据人眼的亮度感知系统调节出来的参数。


void ConvertRGB2GRAY(const Mat& image, Mat& imageGray)
{
    if (!image.data || image.channels() != 3)
    {
        return;
    }
    //创建一张单通道的灰度图像
    imageGray = Mat::zeros(image.size(), CV_8UC1);
    //取出存储图像像素的数组的指针
    uchar* pointImage = image.data;
    uchar* pointImageGray = imageGray.data;
    //取出图像每行所占的字节数
    size_t stepImage = image.step;
    size_t stepImageGray = imageGray.step;

    
    for (int i = 0; i < imageGray.rows; i++)
    {
        for (int j = 0; j < imageGray.cols; j++)
        {
            //opencv的通道顺序是BGR,而不是我们常说的RGB顺序
            pointImageGray[i * stepImageGray + j] =
                (uchar)(0.114 * pointImage[i * stepImage + 3 * j] +
                    0.587 * pointImage[i * stepImage + 3 * j + 1] +
                    0.299 * pointImage[i * stepImage + 3 * j + 2]);
        }
    }
}

在多通道图像中,比如RGB图像是这样保存的

int  widthStep;   /* 排列的图像行大小,以字节为单位 */
int  nChannels;     /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */

图像矩阵是一个二维数组,不论是灰度图像还是彩色图像,在计算机内存中都是以一维数组的形式存储的。用Mat存储一幅图像时,若图像在内存中是连续存储的(Mat对象的isContinuous == true),则可以将图像的数据看成是一个一维数组,而其data(uchar*)成员就是指向图像数据的第一个字节的,因此可以用data指针访问图像的数据。

如果想要遍历其中的元素,可以使用指针的遍历方法


uchar* data=(uchar *)img->imageData;
int step = img->widthStep/sizeof(uchar);
int channels = img->nChannels;
uchar *b,*g,*r;
for(int i=0;i<img->height;i++)
     for(int j=0;j<img->width;j++){
           *b=data[i*step+j*chanels+0];
           *g=data[i*step+j*chanels+1];
           *r=data[i*step+j*chanels+2];
      }

下面我们来看一看用这几种方法进行灰度转化的结果

#include <opencv2\opencv.hpp>
using namespace cv;
void ConvertRGB2GRAY(const Mat& image, Mat& imageGray);

int main()
{
    Mat src = imread("C:\\Users\\32498\\Pictures\\16.png");
    Mat src0 = imread("C:\\Users\\32498\\Pictures\\16.png",0);
    Mat grayImage;
    Mat cvt_gray_image;

    //读入的彩色图
    namedWindow("origin_image", WINDOW_NORMAL);
    imshow("origin_image", src);

    //opencv使用imread函数读入彩色图,设置第二个参数为0得到的灰度图
    namedWindow("opencv_image", WINDOW_NORMAL);
    imshow("opencv_image", src0);

    //使用公式GRAY=0.299*R+0.587*G+0.114*B
    ConvertRGB2GRAY(src, grayImage);
    namedWindow("my_gray_image", WINDOW_NORMAL);
    imshow("my_gray_image", grayImage);

    //先读入彩色图,然后使用cvtColor函数进行灰度转化
    cvtColor(src, cvt_gray_image,COLOR_BGR2GRAY);
    namedWindow("cvt_gray_image", WINDOW_NORMAL);
    imshow("cvt_gray_image", cvt_gray_image);
    waitKey(0);
    return 0;
}

void ConvertRGB2GRAY(const Mat& image, Mat& imageGray)
{
    if (!image.data || image.channels() != 3)
    {
        return;
    }
    //创建一张单通道的灰度图像
    imageGray = Mat::zeros(image.size(), CV_8UC1);
    //取出存储图像像素的数组的指针
    uchar* pointImage = image.data;
    uchar* pointImageGray = imageGray.data;
    //取出图像每行所占的字节数
    size_t stepImage = image.step;
    size_t stepImageGray = imageGray.step;

    
    for (int i = 0; i < imageGray.rows; i++)
    {
        for (int j = 0; j < imageGray.cols; j++)
        {
            //opencv的通道顺序是BGR,而不是我们常说的RGB顺序
            pointImageGray[i * stepImageGray + j] =
                (uchar)(0.114 * pointImage[i * stepImage + 3 * j] +
                    0.587 * pointImage[i * stepImage + 3 * j + 1] +
                    0.299 * pointImage[i * stepImage + 3 * j + 2]);
        }
    }
}


本文转载自: https://blog.csdn.net/yangSHU21/article/details/130237669
版权归原作者 yangSHU21 所有, 如有侵权,请联系我们删除。

“利用OpenCV把一幅彩色图像转换成灰度图”的评论:

还没有评论