目录

1.cvtColor的用处和API讲解

1.cvtColor的作用

2.cvtColor的API

2.用代码实现cvtColor的颜色转换功能

1.调用imread读取RGB彩色图像

2.把RGB图像转换为YUV图像

3.调用imread读取YUV灰度图像

4.把YUV图像转换为RGB图像

5.把处理过后的两种图像保存

注:

1.灰度图

2.YUV

3.cvtColor(img_yuv,img_to_bgr,CV_YUV2BGR);

3.putText的用处和API讲解

3.1. putText的用法和作用

3.2. putText的API

3.3. 用代码实现putText的功能


1.cvtColor的用处和API讲解

1.cvtColor的作用

cvtColor是OPENCV里面颜色转换的转换函数,它的功能非常强大。能够实现RGB图像转换成灰度图、灰度图转换成RGB图像、RGB转换成HSV等等。下面我们来看看

2.cvtColorAPI

CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );

第一个参数:输入的图像数据

第二个参数:输出的图像数据

第三个参数:颜色转换的标识符,下面是转换的图表。图像转化可以分为11个大类,分别是RGB->BGRRGB->5X5 RGB->GRAYRGB->CIEXYZRGB->YyCrcb(YUV)RGB->HSVRGB->HLSRGB->CIELabRGB->CIELuvRGB->BayerYUV420->RGB

第四个参数:目标图像通道数,默认为0

    2.用代码实现cvtColor的颜色转换功能

    这次代码主要是转换几个常见的格式,如RGB->YUV, YUV->RGB。具体的代码思路如下:

    这个代码里面我们分别读取两种图片,一种是RGB图片、另外一种是YUV灰度图像、分别用cvtColor把RGB图像转换成YUV图像、把YUV灰度图像转换成RGB图像、最后用imwrite保存两种图片。下面是一些代码的实现截图:

    1.调用imread读取RGB彩色图像

    读取RGB彩色通道的图像,这张图片是一张车辆的图片

    2.RGB图像转换为YUV图像

    调用cvtColor把三通道的RGB图像转换为YUV的灰度图像,这里使用的是COLOR_RGB2YUV。

    3.调用imread读取YUV灰度图像

    读取YUV的灰度图像,这张图片是一张灰度的汽车图像

    4.YUV图像转换为RGB图像

    调用cvtColor把单通道的图像转换成RGB图像,调用的选项使用的是COLOR_YUV2RGB

    5.把处理过后的两种图像保存

    使用imwrite保存两种图像

    最终的效果:

    左边是处理后的YUV图像,右边是RGB图像

    #include <opencv2/opencv.hpp>
    #include <opencv2/dnn.hpp>
    #include <opencv2/imgcodecs.hpp>
    #include <opencv2/imgproc.hpp>
    #include <iostream>
    
    using namespace cv; //Must Need Write cv
    using namespace std;
    
    int main()
    {
    
        Mat src_bgr = imread("car.jpg");
    
        Mat img_yuv;
        cvtColor(src_bgr,img_yuv,COLOR_BGR2YUV);
        imwrite("car_yuv.jpg",img_yuv);
    
        Mat img_gray;
        cvtColor(src_bgr,img_gray,COLOR_BGR2GRAY);
        imwrite("car_gray.jpg",img_gray);
    
        Mat img_bgr;
        cvtColor(img_yuv,img_bgr,COLOR_YUV2BGR);
        imwrite("car_bgr.jpg",img_bgr);
    
        return 0;
    }
    
    

    car.jpg                                                                car.yuv

    car.gray                                                                car.bgr

    注:

    1.灰度图

    当你用灰度模式(例如 OpenCV 中的 cv2.IMREAD_GRAYSCALE 或相机 SDK 中的灰度采集)读取或采集图像时,图像数据变成了单通道

    • 彩色图:每个像素由 3 个值组成(蓝、绿、红),是一个三维矩阵 (Height,Width,3)
    • 灰度图:每个像素由 1 个值组成(亮度),是一个二维矩阵 (Height,Width)

    在这个过程中,程序将彩色的信息通过加权平均算法(例如 Gray = 0.299R+0.587G+0.114BGray = 0.299R+0.587G+0.114B)合并成了一个亮度值。原本的 R、G、B 三个数值彻底丢失了,只剩下一个亮度值。

    然后你对灰度图做了转BGR

    # gray 是单通道的图像
    cvtColor(img_gray,img_bgr ,COLOR_GRAY2BGR)

    这行代码做了以下事情:

    1. 输入:一个单通道的矩阵,数值是亮度 L。
    2. 输出:一个三通道的矩阵。
    3. 转换逻辑:为了让单通道变成三通道,程序将唯一的亮度值 L 复制到了三个通道上。
    • 原来的像素值 L
    • 转换后的像素值 = (B = L, G = L, R = L)

    当三个通道的值相等时,在屏幕上显示出来的就是灰度色(因为没有任何色彩倾向)。所以虽然图像格式变成了 BGR,但视觉上依然是灰色的。

    2.YUV

    yuv的图像用rgb读取,能转成彩色的。

     YUV 和 RGB 一样,都完整保留了彩色信息,只是用不同的数学方式表达而已。

    而之前你遇到的灰度转 BGR 之所以不行,是因为灰度图只保留了亮度,丢失了色彩信息。让我们深入看看区别:

    YUV 格式本身就包含彩色信息

    YUV(以及类似的 YCbCr)并不是黑白格式,而是一种彩色编码格式。它包含三个分量:

    • Y(亮度):描述图像的明暗程度(类似于黑白图)
    • U(Cb,蓝色色度):描述蓝色分量与亮度的差异
    • V(Cr,红色色度):描述红色分量与亮度的差异

    关键点:虽然 Y 通道看起来像灰度图,但 UV 通道完整保留了颜色信息!这和灰度图(只有 Y,没有 UV)有本质区别。

    CV_BGR2YUV 和 CV_BGR2YUV_I420 的主要区别在于:前者生成的是“平面”但未压缩的格式,后者生成的是“平面且压缩”的格式

    • YUV444(如通过 CV_BGR2YUV 转换)
      • 转换结果是 3 通道图像(CV_8UC3)。它的形状是 (Height, Width, 3),数据总量就是 Height * Width * 3 字节。
    • YUV420(如通过 CV_BGR2YUV_I420 转换)
      • 转换结果是 1 通道图像(CV_8UC1)。为了把 Y、U、V 数据都塞进一个通道里,OpenCV 会把它们垂直堆叠起来,形成一个更高、但宽度不变的图像。所以它的形状是 (Height * 3/2, Width, 1)

    数据量计算对比

    我们用一张 2x2 的图片来实际算一下,就更清晰了:

    BGR 原图
    大小:2x2 像素
    数据量:12 字节
    Mat(2, 2, CV_8UC3)

    转换为 YUV444
    存储方式:三通道,每个像素的 Y、U、V 各占一个字节
    矩阵形状:(2, 2, 3)
    数据总量:2*2*3 = 12 字节

    转换为 YUV420(I420)
    存储方式:单通道,垂直堆叠
    矩阵形状:(3(2*1.5), 2, 1),因为 2 * 3/2 = 3
    数据总量:3*2*1 = 6 字节

    YUV420(家族名称)
        ├── I420(也叫 IYUV):YYYYYYYY UU VV (平面格式)
        ├── YV12:YYYYYYYY VV UU (平面格式,UV顺序交换)
        ├── NV12:YYYYYYYY UVUV (半平面格式)
        └── NV21:YYYYYYYY VUVU (半平面格式)

    1. I420:Y平面 + U平面 + V平面
    2. NV12:Y平面 + UV交错平面(UV交替存储)
    3. YV12:Y平面 + V平面 + U平面(顺序不同)

    3.cvtColor(img_yuv,img_to_bgr,CV_YUV2BGR);

    COLOR_BGR2YUVI420  -->  COLOR_YUV2BGR 有问题

    当你将BGR转换为YUV_I420格式时,YUV图像的大小计算方式与BGR不同。I420格式要求图像的宽度和高度都是偶数,因为它的UV分量是下采样的(每2x2的Y块对应一组UV)。

    COLOR_BGR2YUV  -->  COLOR_YUV2BGR 没有问题

    3.putText的用处和API讲解

    3.1. putText的用法和作用

    putText是OPENCV中常见的功能,他主要的功能是在Mat矩阵里面显示文字,像下图

    从上图可以看出来putText是通过坐标(X,Y)在矩阵显示文字

    3.2. putTextAPI

    CV_EXPORTS_W void putText( InputOutputArray img, const String& text, Point org,

                             int fontFace, double fontScale, Scalar color,

                             int thickness = 1, int lineType = LINE_8,

                             bool bottomLeftOrigin = false );

    第一个参数:img需要传入的图像数据

    第二个参数:text需要显示的文字

    第三个参数:org文字在图像数据中的坐标位置

    第四个参数:fontFace字体类型,常用的字体类型如下

    • FONT_SHERSHEY_SIMPLEX
    • FONT_HERSHEY_ PLAIN
    • FONT_HERSHEY_DUPLEX
    • FONT_SHERSHEY_SCOMPLEX
    • FONT_SHERSHEY_STRIPLEX
    • ONT_SHERSHEY_SCOMPLEX_SSMALL
    • FONT_HERSHEY_SCRIPT_SIMPLEX
    • orFONT_SHERSHEY_SSCRIPT_SCOMPLEX

    以上所有类型都可以配合FONT_HERSHEY_ITALIC使用,产生斜体效果

    第五个参数:fontScale字体的大小

    第六个参数:color是颜色标量,字体的显示颜色

    第七个参数:thickness是字体的粗细程度,默认为1

    第八个参数:lineType线性,默认是LINE_8,具体的几个如下:

    第九个参数:bottomLeftOrigin图像数据原点在左下角, Otherwise(默认false)图像数据中原点的左上角。默认bottomLeftOrigin = false

    3.3. 用代码实现putText的功能

    本章节代码主要是实现单张图片显示文字

    3.3.1.读取车辆图片

    使用imread读取需要处理的图片

    3.3.2.调用putText的API进行文字显示

    上面是代码是利用putText对Mat矩阵进行文字显示,显示的字符是HelloWorld,这里的位置我们选择是Point(0,400)这个位置,字体选择FONT_HERSHEY_PLAIN,字体大小是4.0,颜色为红色(Scalar(0,0,255)), 绘制线的粗细程度是4,然后线的类型是LINE_8.

    3.3.3.最后用imwrite来保存图片,最终的显示效果是

    #include <opencv2/opencv.hpp>
    #include <opencv2/dnn.hpp>
    #include <opencv2/imgcodecs.hpp>
    #include <opencv2/imgproc.hpp>
    #include <iostream>
    
    using namespace cv; //Must Need Write cv
    using namespace std;
    
    int main()
    {
    
        Mat img = imread("car.jpg");
        if(img.empty())
        {
            printf("imread error\n");
            return -1;
        }
    
        string str = "Your Car";
        Point pt(0,400);
        int fontFace = cv::FONT_HERSHEY_PLAIN;
        double fontScale = 4.0;
        int thinkness = 4;
        putText(img,str,pt,fontFace,fontScale,Scalar(0,0,255),thinkness);
    
        imwrite("car_text.jpg",img);
    
        return 0;
    }
    
    
    Logo

    腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

    更多推荐