欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > OPENCV的cvtColor和putText的讲解

OPENCV的cvtColor和putText的讲解

2025/8/4 15:55:05 来源:https://blog.csdn.net/2202_75840803/article/details/148540918  浏览:    关键词:OPENCV的cvtColor和putText的讲解

一.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

常用的:

  • COLOR_BGR2GRAY:彩色图像转灰度图
  • COLOR_GRAY2BGR:灰度图转彩色图像(每个通道值相同)

  • COLOR_BGR2HSV:BGR 转 HSV(色相、饱和度、亮度)
  • COLOR_HSV2BGR:HSV 转 BGR

  • COLOR_BGR2YCrCb:BGR 转 YCrCb(亮度、红色差、蓝色差)
  • COLOR_YCrCb2BGR:YCrCb 转 BGR

                Y:亮度分量

                Cr:红色分量与亮度的差值

                Cb:蓝色分量与亮度的差值

  • COLOR_BGR2Lab:BGR 转 Lab(亮度、a 通道、b 通道)
  • COLOR_Lab2BGR:Lab 转 BGR

                L:亮度,0-100

                a:从绿色到红色的范围

                b:从蓝色到黄色的范围

  • COLOR_BGR2YUV:BGR 转 YUV(亮度、色度)
  • COLOR_YUV2BGR:YUV 转 BGR

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

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

1.流程

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

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

​​​​#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>using namespace cv;
using namespace std;int main()
{// 读取彩色图片Mat img1 = imread("people.jpg");if(img1.empty()){cerr << "无法读取彩色图片 people.jpg" << endl;return -1;}cout << "成功读取彩色图片,通道数: " << img1.channels() << endl;// 读取灰度图片Mat img2 = imread("gray.jpeg", IMREAD_GRAYSCALE);if(img2.empty()){cerr << "无法读取灰度图片 gray.jpeg" << endl;return -1;}cout << "成功读取灰度图片,通道数: " << img2.channels() << endl;// 正确转换:BGR转灰度Mat img1_gray;cvtColor(img1, img1_gray, COLOR_BGR2GRAY);if(img1_gray.empty()){cerr << "彩色图转灰度图失败" << endl;return -1;}cout << "彩色图转灰度图成功,通道数: " << img1_gray.channels() << endl;// 正确转换:灰度图转回BGR彩色图Mat img2_bgr;cvtColor(img2, img2_bgr, COLOR_GRAY2BGR);if(img2_bgr.empty()){cerr << "灰度图转彩色图失败" << endl;return -1;}cout << "灰度图转彩色图成功,通道数: " << img2_bgr.channels() << endl;// 如果确实需要YUV格式,可以这样转换Mat img2_yuv;cvtColor(img2_bgr, img2_yuv, COLOR_BGR2YUV);if(img2_yuv.empty()){cerr << "BGR转YUV失败" << endl;return -1;}cout << "BGR转YUV成功,通道数: " << img2_yuv.channels() << endl;// 保存处理后的图像imwrite("img1_gray.jpg", img1_gray);imwrite("img2_bgr.jpg", img2_bgr);imwrite("img2_yuv.jpg", img2_yuv);cout << "所有图像保存成功" << endl;return 0;
}

                                原图                                                处理后

   

                原图                                        yuv                                         bgr

   

2.错误分析

 1.OpenCV 默认读取的是 BGR 格式,应该使用COLOR_BGR2GRAY,而不是COLOR_RGBGRAY,虽然不会有错误,也可以使用,但是不规范。

2.灰度图转换出现的问题

读取灰度图的时候不可以直接    Mat img2 = imread("gray.jpeg");

不指定参数时,imread默认以彩色模式(IMREAD_COLOR)读取图像,即使原图是灰度图。

即使原图是灰度图OpenCV 仍会将其读取为 3 通道(BGR 格式)图像,每个通道的值相同。

例如,原图中像素值为 128 的点,会被读取为 [128, 128, 128](BGR 三个通道)。

所以需要这样子读取

 // 读取灰度图片
    Mat img2 = imread("gray.jpeg", IMREAD_GRAYSCALE);

指定 IMREAD_GRAYSCALE 的效果

强制 OpenCV 将图像读取为单通道(灰度)图像,无论原图是什么格式。

图像数据将被压缩为单通道,减少内存占用,且符合后续灰度图像处理的预期。

为什么要这样子?

如果直接使用 imread("gray.jpeg")(不指定参数),可能引发以下问:

1.通道数不匹配:

        若后续代码假设 img2 是单通道灰度图(如调用 COLOR_GRAY2BGR),但实际读取的是 3 通道彩色图,会触发 "Invalid number of channels" 错误。如下

terminate called after throwing an instance of 'cv::Exception'what():  OpenCV(3.4.12) /home/yifeng/Downloads/opencv-3.4.12/modules/imgproc/src/color.simd_helpers.hpp:88: error: (-2:Unspecified error) in function 'cv::impl::{anonymous}::CvtHelper<VScn, VDcn, VDepth, sizePolicy>::CvtHelper(cv::InputArray, cv::OutputArray, int) [with VScn = cv::impl::{anonymous}::Set<1>; VDcn = cv::impl::{anonymous}::Set<3, 4>; VDepth = cv::impl::{anonymous}::Set<0, 2, 5>; cv::impl::{anonymous}::SizePolicy sizePolicy = (cv::impl::<unnamed>::SizePolicy)2; cv::InputArray = const cv::_InputArray&; cv::OutputArray = const cv::_OutputArray&]'
> Invalid number of channels in input image:
>     'VScn::contains(scn)'
> where
>     'scn' is 3Aborted (core dumped)

2.占用内存

灰度图本身只需 1 通道存储,但被读取为 3 通道会占用 3 倍内存

三.putText的用处和API讲解

1. putText的用法和作用

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

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

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字体类型,常用的字体类型如下:

基本无衬线字体(Sans-Serif)

        FONT_HERSHEY_SIMPLEX,

        最简单的无衬线字体,笔画粗细一致,字符结构清晰。常用于需要简洁、易读的文本标注,如物体检测结果、图像分析数据等。

        FONT_HERSHEY_PLAIN,比 SIMPLEX 更简单的变体,字符更细、更紧凑。适合空间有限的场景,如小尺寸图像中的标注。

        FONT_HERSHEY_DUPLEX,比 SIMPLEX 更复杂的无衬线字体,部分字符有双线条效果。视觉上更丰富,但保持了良好的可读性。

复杂无衬线字体

        FONT_HERSHEY_COMPLEX,复杂的无衬线字体,字符结构更精细,部分笔画有变化。适合需要一定美观度的文本,如演示文稿中的图像标注。

        FONT_HERSHEY_TRIPLEX,最复杂的无衬线字体,类似 DUPLEX 但更精细,某些字符有三线条效果。视觉效果丰富,常用于需要强调的文本。

        FONT_HERSHEY_COMPLEX_SMALL,COMPLEX 的小型变体,字符更小但保持了相同的结构复杂度。适合需要在小空间内显示详细信息的场景。

手写风格字体

        FONT_HERSHEY_SCRIPT_SIMPLEX,手写风格的简化字体,模拟手写体的流畅性。适合需要个性化或非正式风格的文本。

        FONT_HERSHEY_SCRIPT_COMPLEX,更复杂的手写风格字体,笔画变化更丰富,接近书法效果。常用于需要艺术感的文本,如标题或装饰性文字。

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

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

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

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

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

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

四.putText代码实战

1.cvColor

2.putText

流程:

#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>using namespace cv;
using namespace std;int main()
{Mat img = imread("people.jpg");if(img.empty()){cerr<<"imread people.jpg failed\n "<<endl;std::cout<<"imread people.jpg failed\n "<<std::endl;}cerr<<"imread people.jpg successed\n "<<endl;std::cout<<"imread people.jpg successed\n "<<std::endl;string str="hello world 你好世界!";//要现实的文本//参数三:显示的位置Point located;located.x = 0;located.y=400;//参数四:字体格式int fontFace = cv::FONT_HERSHEY_SCRIPT_SIMPLEX;//字体大小double fontScale = 5.0;//字体粗细int thickness = 4;putText(img,str,located,fontFace,fontScale,Scalar(255,0,0),thickness,LINE_8);imwrite("putText.jpg",img);
return  0;
}

我们代码中显示内容我们输入了中文,可结果却无法显示,这是因为putText它不提供字库,显示中文需要使用freeType等文字库

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词