【OpenCV(C++)快速入门】--中篇--OpenCV中对图像的处理

【专栏介绍】因为专业需要用到OpenCV来处理图像数据,所以需要学习,搜索了网上的相关资料,整体知识比较零散,花费了较多时间,所以才萌生了将学习过程整理成专栏的形式,希望能帮到后来的人,也方便自己复习。如有错漏欢迎评论或者私信指出,我定当及时更正。

本系列共有上中下三篇,后面有空会再做个小项目,并放出来。

上篇:https://blog.csdn.net/weixin_45703465/article/details/122583084https://blog.csdn.net/weixin_45703465/article/details/122583084

中篇:OpenCV中对图像的处理

下篇:OpenCV中的颜色、形状、人脸和轮廓检测

【OpenCV(C++)快速入门】--下篇--OpenCV中的颜色、形状、人脸和轮廓检测_山海里啊有星辰的博客-CSDN博客

2 OpenCV中的基本操作

2.1 图像及视频的读取及显示

2.1.1 图像的读取

图像的读取是使用OpenCV最最最基本的操作,我们使用如下的方式进行读取。

imread( const String& filename, int flags = IMREAD_COLOR )
    //参数解读: filename 文件路径,可以是相对路径也可以是绝对路径。
    //IMREAD_COLOR 可以从cv::ImreadModes 中选择不同的读取模式,初学使用默认的就可以,非必须的参数。

2.1.2 视频的读取

OpenCV 对视频的读取使用了VideoCapture 这个类,下面列出了初学常用的几个构造函数。

VideoCapture();//默认的构造函数
VideoCapture(const String& filename);//filename 为需要打开视频的路径
VideoCapture(int index);//如果需要打开本地摄像头,使 index = 0 即可, 插了usb摄像头的话 使用 index =1

2.1.3 图像的显示

无论是视频还是单张图像我们都可以使用下面的函数进行显示:

void imshow(const String& winname, InputArray mat);//参数1 是窗口名称 参数2 需要显示的图像的名称
int waitKey(int delay = 0);
//一般会和imshow()联合使用,否则图像一闪而过,delay 的单位是ms, delay=0代表永远不关闭

2.1.4 代码实践

下面进行代码的实践,帮助更好的理解。

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

#include "iostream"

using namespace std;
using namespace cv;

void imgread_show() {
    ///  单张图片的读取及显示 ///
    string path = "./test.png";//需要显示的图片的路径,这里是相对路径
    Mat img = imread(path);//实例化一个图像对象
    imshow("Image", img);//进行图片的显示,显示窗口名称为 Image
    waitKey(0);//等待按键以结束
}
void videoread_show() {
    /// 视频的读取及显示 
    string path_video = "./test_video.mp4";//视频路径
    Mat img_video;
    VideoCapture cap(path_video);//实例化视频对象

    while(true) {
        cap.read(img_video);//一帧一帧的读取视频中的图像
        imshow("Video", img_video);
        waitKey(20); //延时20ms,这个时间越短视频播放越快
    }
}
void webcam() {
     /// 读取网路摄像头的数据 ///
    Mat img;
    VideoCapture webcam(0);
    while (true) {
        webcam.read(img);
        imshow("Webcam", img);
        waitKey(1);
    }        
}
int main() {
    //一次取消一行注释进行测试
    imgread_show();
    //videoread_show();
    //webcam();   
    return 0;
}

这里就不放效果图了,自己找张图片和小视频试一下,应该问题不大。

2.2 图像的基本处理

这里介绍几种最最基本的图像处理函数:

// 转换图片的颜色空间(可以把彩色图片转为灰度图)
void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
//给图片添加高斯模糊的效果
void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
                                double sigmaX, double sigmaY = 0,
                                int borderType = BORDER_DEFAULT );
//该函数在输入图像中查找边缘,并使用 Canny 算法在输出图像边缘中标记它们(边缘检测)
void Canny( InputArray image, OutputArray edges,
                         double threshold1, double threshold2,
                         int apertureSize = 3, bool L2gradient = false );
//通过使用特定的结构元素来扩大图像。(有加粗放大的效果)特定的结构会在后面介绍
void dilate( InputArray src, OutputArray dst, InputArray kernel,
                          Point anchor = Point(-1,-1), int iterations = 1,
                          int borderType = BORDER_CONSTANT,
                          const Scalar& borderValue = morphologyDefaultBorderValue() );
//给图像添加侵蚀效果
void erode( InputArray src, OutputArray dst, InputArray kernel,
                         Point anchor = Point(-1,-1), int iterations = 1,
                         int borderType = BORDER_CONSTANT,
                         const Scalar& borderValue = morphologyDefaultBorderValue() );

2.2.1 cvtColor() 颜色空间转换

void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
//src 为源图像 dst 效果施加后输出的图像--这两个参数含义对本节所列函数都适用

code 为颜色空间的编码,可以在一个枚举变量 ColorConversionCodes 中查到。

dstCn 为输出图像的通道数,默认值为0,也就是默认和源图像保持一致。

2.2.2 GaussiaBlur() 高斯模糊

void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
                                double sigmaX, double sigmaY = 0,
                                int borderType = BORDER_DEFAULT );

ksize 该参数是Size 类型的,是一个OpenCV自定义的数据类型。用于指定图像或矩形大小的模板类。包含两个成员变量width 和 height。在该函数下,width 和 height 只能是正奇数,数字越大模糊效果越明显。如果为0了,则该参数无效,使用sigmaX 和 sigmaY来决定模糊程度。

sigmaX, sigmaY 分别为X和Y 方向的高斯核标准差。如果sigmaY为0,它将被设置为和sigmaX相等。这一对参数的作用同ksize ,使用这两个参数中的一种即可。

2.2.3 Canny() 边缘检测

void Canny( InputArray image, OutputArray edges,
                         double threshold1, double threshold2,
                         int apertureSize = 3, bool L2gradient = false );
//image 为源图像 edges 为检测边缘后输出的图像

threshold1 threshold2 这是两个阈值,通过调节这两个阈值来调节边缘检测的效果。

后面两个参数,初学保持默认就可以。

2.2.4 dilate() 图像扩大

void dilate( InputArray src, OutputArray dst, InputArray kernel );

kernel 就是上面提到的特点的结构,它本身是 Mat 类型的。使用如下的方式获得:

Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3));
//Size中的数字越大,效果越明显

2.2.5 erode() 图像侵蚀

void erode( InputArray src, OutputArray dst, InputArray kernel );

这里的kernel 同2.2.4。

2.2.6 实践

在接下来的实践中,我们将对下面的图片(图片来自《凡人修仙传》)进行处理。

【OpenCV(C++)快速入门】--中篇--OpenCV中对图像的处理_第1张图片

我们来看一下经过上面处理过后的图片各自的效果:
【OpenCV(C++)快速入门】--中篇--OpenCV中对图像的处理_第2张图片

源代码:

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

#include "iostream"

using namespace std;
using namespace cv;
 Import Images  /

int main() {
    string path = "./1.png";
    Mat img = imread(path);
    resize(img, img,Size(), 0.5, 0.5);//这里将图片缩小了,方便截图
    Mat imgGray, imgBlur, imgCanny, imgDil, imgErode;
    cvtColor(img, imgGray, COLOR_BGR2GRAY);//convert the img to other style img
    
    GaussianBlur(img, imgBlur, Size(3, 3), 3, 0);
    Canny(img, imgCanny, 25, 75);//可以更改后面的参数来看看效果
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3));
    dilate(imgCanny, imgDil, kernel);
    erode(imgDil, imgErode, kernel);
    
    imshow("Image", img);
    imshow("Gray", imgGray);
    imshow("Blur", imgBlur);
    imshow("Canny", imgCanny);
    imshow("Dilation", imgDil);
    imshow("Erode", imgErode);
    waitKey(0);
    return 0;
}

2.3 调整图像大小及图像的裁减

2.3.1 调整图像大小

 void resize( InputArray src, OutputArray dst,
                          Size dsize, double fx = 0, double fy = 0,
                          int interpolation = INTER_LINEAR );

这里可以使用dsize 或着 fx,fy进行图片大小的设定。

dsize(width, height) 指定调整后图片长宽比;

fx fy 缩放比例,小于一为缩小,大于一为放大

2.3.2 裁减图像

这里的裁减指的是获得原始图像的一部分图像,即从原图像上截取一块下来,为了达到这个目的,我们需要先定义一个矩形:

Rect roi(200, 100, 300, 300);
//参数含义:定义该矩形左上角坐标为(200,100),长宽为300x300

然后使用下面的函数即可获得裁减后的图像:

imgCrop = img(roi);//img为原图像
//imgCrop = img(Rect(200,100,300,300)) 也可以

2.3.3 实践

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

#include "iostream"
using namespace std;
using namespace cv;
int main() {
    string path = "./1.png";
    Mat img = imread(path);
    Mat imgRsize, imgCrop;
    resize(img, imgRsize, Size(680,400));//use the Size() to specify the szie
    //resize(img, imgRsize, Size(), 0.5, 0.5);//use 'fx fy' to zoom in or out
    Rect roi(200, 100, 300, 300);
    imgCrop = img(roi);
    imshow("Image", img);
    imshow("Resize", imgRsize);
    imshow("Crop", imgCrop);
    waitKey(0);
    return 0;
}

效果如下:

【OpenCV(C++)快速入门】--中篇--OpenCV中对图像的处理_第3张图片
【OpenCV(C++)快速入门】--中篇--OpenCV中对图像的处理_第4张图片

2.4 在图像中进行绘制及文字的添加

这小节我们简单点,从实践开始:

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "iostream"
using namespace std;
using namespace cv;
int main() {
    / 定义一个空白图片 
    // 参数含义依次是图片长、图片宽、图像格式(8bit,三通道)、颜色(B G R)
    Mat img(512, 512, CV_8UC3, Scalar(255, 255, 255));
    / 画图及添加文字 
    //参数含义依次是目标图片、圆心坐标、半径长、颜色、填充(如果为数字则代表圆线条粗细)
    circle(img, Point(256, 256), 155, Scalar(0, 255, 0), FILLED);
    circle(img, Point(256, 256), 155, Scalar(0, 0, 0), 5);
    //参数含义:目标图片、矩形左上角点坐标、矩形右上角点坐标、颜色、填充(如果为数字则代表圆线条粗细)
    rectangle(img, Point(130,226), Point(382, 296), Scalar(255,255,255), FILLED);
    //参数含义:目标图片、线段起点坐标、线段终点坐标、颜色、数字则表圆线条粗细
    line(img, Point(130, 296), Point(382, 296), Scalar(255,255,10), 2);
	//参数含义:目标图片、文字内容、文本框左下角点坐标、字体样式、字体大小、颜色、字体粗细
    putText(img, "OMG!", Point(137, 262), FONT_HERSHEY_DUPLEX, 0.75, Scalar(12,13,14),1);
    imshow("Image", img);

    waitKey(0);    
    return 0;
}

上面项目输出的图片长这个样子:

【OpenCV(C++)快速入门】--中篇--OpenCV中对图像的处理_第5张图片

参考声明:

本篇是基于国外一个大神OpenCV教程写的,这是他的主页,https://www.murtazahassan.com/,有能力的朋友可以去看看。

你可能感兴趣的:(OpenCV快速入门,opencv,计算机视觉,c++)