Linux43:cvtColor和puttext
cvtColor是OPENCV里面颜色转换的转换函数,它的功能非常强大。能够实现RGB图像转换成灰度图、灰度图转换成RGB图像、RGB转换成HSV等等。下面我们来看看。
目录
3.cvtColor(img_yuv,img_to_bgr,CV_YUV2BGR);
1.cvtColor的用处和API讲解
1.cvtColor的作用
cvtColor是OPENCV里面颜色转换的转换函数,它的功能非常强大。能够实现RGB图像转换成灰度图、灰度图转换成RGB图像、RGB转换成HSV等等。下面我们来看看
2.cvtColor的API
CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
第一个参数:输入的图像数据
第二个参数:输出的图像数据
第三个参数:颜色转换的标识符,下面是转换的图表。图像转化可以分为11个大类,分别是RGB->BGR、RGB->5X5、 RGB->GRAY、RGB->CIEXYZ、RGB->YyCrcb(YUV)、RGB->HSV、RGB->HLS、RGB->CIELab、RGB->CIELuv、RGB->Bayer、YUV420->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)
这行代码做了以下事情:
- 输入:一个单通道的矩阵,数值是亮度 L。
- 输出:一个三通道的矩阵。
- 转换逻辑:为了让单通道变成三通道,程序将唯一的亮度值 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 (半平面格式)
- I420:Y平面 + U平面 + V平面
- NV12:Y平面 + UV交错平面(UV交替存储)
- 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. putText的API
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;
}
更多推荐


所有评论(0)