从零开始:数字图像处理的编程基础与应用
上QQ阅读APP看书,第一时间看更新

1.6 图像属性与基本图形绘制

本节将介绍图像的属性定义和表示方法,以及如何绘制基本图形(如直线、矩形和圆形)。

· 1.6.1 图像属性

█ 1. 画点 cv::Point()

OpenCV中使用cv::Point()表示其图像坐标和指定的2D点。cv::Point()类的对象创建有两种方式:第一种是使用构造函数,第二种是使用成员变量赋值。具体示例如下。

Point pt = Point(x,y) // 第一种方式:使用构造函数
Point pt; // 第二种方式:使用成员变量赋值
Pt.x = 10;
Pt.y = 8;

█ 2. 定义颜色 cv::Scalar()

OpenCV中使用cv::Scalar()类来表示一个4元素的向量。其定义如下。

Scalar scalar(
double val[4];
)

Scalar类型被广泛应用于OpenCV中,常用于传递像素值,也常用于表示BGR颜色值(3个参数)。如果不使用最后一个参数,则无须定义最后一个参数。

当要定义一个颜色参数时,可以通过Scalar( a, b, c )来表示。例如,当要定义一个RGB颜色时,可以使Blue = a、Green = b、Red = c。

█ 3. 设置尺寸 cv::Size()

OpenCV中图像的大小可以通过cv::Size类来表示,第一个参数width表示图像的宽度,第二个参数height表示图像的高度,其定义如下。

cv::Size(
int _width,
int _height
)

这里介绍的是Size类的简单使用方法,即可以通过“Size size(5, 10);”语句创建对象,通过size.width和size.height访问对象数据成员。

· 1.6.2 基本图形绘制

█ 1.绘制直线

cv::line()函数用于在图像中绘制连接点pt1和点pt2的直线。cv::line()函数定义如下。

void cv::line(
inputOutputArray img,//图像
Point pt1,//点1
Point pt2,//点2
const Scalar & color,//绘制直线的颜色
int thickness = 1,//直线的厚度
int lineType = LINE_8,//直线的类型
int shief = 0 //点坐标中的小数位数
)

█ 2.绘制矩形

cv::rectangle()函数用于绘制矩形。OpenCV中通过cv::Rect类定义矩形,Rect矩形类包括Point点类的成员x和y(表示矩形的左上角)以及size类的成员width和height(表示矩形的大小)。但是,矩形类不会从Point点类或size类继承,因此通常不会从它们中继承操作符。其基本定义和使用方法如表1-3所示。

表1-3 cv::Rect类的定义与使用方法

cv::rectangle()函数定义有以下两种形式。

形式一:

   void rectangle(
cv::Mat& img,// 待绘制的图像
cv::Point pt1,// 矩形的第一个顶点
cv::Point pt2 // 矩形的对角顶点
const cv::Scalar& color,// 线条的颜色(RGB)
int lineType = 8,// 线型(4邻域或8邻域,默认为8邻域)
int shift = 0 // 偏移量
);

形式二:

   void rectangle(
cv::Mat& img,// 待绘制的图像
cv::Rect r,// 待绘制的矩形
const cv::Scalar& color,// 线条的颜色(RGB)
int lineType = 8,// 线型(4邻域或8邻域,默认为8邻域)
int shift = 0 // 偏移量
);

█ 3.绘制圆形

cv::circle()函数用于绘制圆形。cv::circle()函数定义如下。

void circle(
cv::Mat& img,// 待绘制的图像
cv::Point center,// 圆心位置
int radius,// 圆的半径
const cv::Scalar& color,// 线条的颜色(RGB)
int thickness = 1,// 线宽
int lineType = 8,// 线型(4邻域或8邻域,默认为8邻域)
int shift = 0// 偏移量
);

下面将通过例1-6展示如何绘制点、直线、矩形和圆形等基本图形(同前面一样,需在1-6.pro文件中导入OpenCV环境配置信息)。

例1-6:基本图形绘制。

具体代码如下。

#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
int main()
{
// 设置窗口
Mat img = Mat::zeros(Size(800,600),CV_8UC3);
img.setTo(255);              // 设置屏幕为白色
Point p1(100,100);          // 点p1
Point p2(758,50);           // 点p2
// 画直线函数
line(img, p1, p2, Scalar(0,0,255), 2);   // 红色
line(img, Point(300,300), Point(758,400), Scalar(0,255,255), 3);
Point p(20,20);//初始化点p的坐标为(20,20)
circle(img,p,1,Scalar(0,255,0),-1);  // 画半径为1的圆形(画点)
Point p4;
p4.x = 300;
p4.y = 300;
circle(img, p4, 100, Scalar(120,120,120), -1);
int thickness = 3;
int lineType = 8;
double angle = 30;  //椭圆旋转角度
ellipse(img, Point(100,100), Size(90,60),angle,0,360, Scalar(255,255,0),thickness,lineType);
// 画矩形
Rect r(250,250,120,200);
rectangle(img,r,Scalar(0,255,255),3);
imshow(“pic”,img);
waitKey();
return 0;
}

程序运行结果如图1-53所示。

图1-53 例1-6程序运行结果

· 1.6.3 颜色空间转换

我们在生活中看到的彩色图像大多数是RGB类型的,但是在进行图像处理时,需要用到灰度、二值、HSV、HSI等颜色空间(又称颜色模式)。OpenCV中提供了cvtColor()函数来实现这些空间之间的相互转换。cvtColor()函数定义如下。

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

该函数的参数解析如下。

  • InputArray src:输入图像,即要进行颜色空间转换的源图像,可以是Mat类。
  • OutputArray dst:输出图像,即进行颜色空间转换后的图像,也可以是Mat类。
  • int code: 转换的代码或标识,即在此确定将什么模式的图像转换成什么模式的图像,后面会详细介绍。
  • int dstCn: 目标图像通道数,如果取值为0,则由src和code决定。

该函数的作用是将图像从一个颜色空间转换到另一个颜色空间。应注意的是,从RGB颜色空间向其他颜色空间转换时,必须明确指出图像的颜色通道。前面提到过,在OpenCV中,默认的颜色排列是BGR而非RGB。所以对于24位颜色图像来说,前8位是蓝色,中间8位是绿色,最后8位是红色。常见的RGB通道的取值范围如下。

  • 0~255:CV_8U类型图像。
  • 0~65535:CV_16U类型图像。
  • 0~1: CV_32F类型图像。

对于线性变换来说,这些取值范围是无关紧要的。但是对于非线性变换,输入的RGB图像必须归一化到其对应的取值范围来获得最终正确的转换结果,例如RGB→CIE L*u*v*转换。如果有一个32位浮点图像直接从8位图像转换而不进行任何缩放,那么它将具有0~255的值范围而不是该函数假定的0~1。所以,在调用cvtColor()函数之前,需要先将图像缩小。

img * = 1./255;
cvtColor(img,img,COLOR_BGR2Luv);

cvtColor()函数中的转换代码(code)如表1-4所示。

表1-4 转换代码(code)表

下面通过例1-7演示cvtColor()函数的使用方法。

例1-7: cvtColor()函数的使用方法。

具体代码如下。

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc,char** argv)
{
Mat src,dst,dst1;
src = imread("D:/images/touxiang.jpg");
//判断图像是否载入成功
if (src.empty())
{
cout<< "can not open the image"<<endl;
return -1;
}
imshow("touxiang.jpg",src);
cvtColor(src,dst,COLOR_BGR2GRAY);//转换方式1,转换为灰度图,经常使用,需要记住
cvtColor(src,dst1,COLOR_BGR2Lab);//转换方式2
imshow("CV_BGR2GRAY change",dst);
imshow("COLOR_BGR2Lab change",dst1);
waitKey(0);
return 0;
}

程序运行结果如图1-54所示。

图1-54 例1-7程序运行结果