【专栏介绍】因为专业需要用到OpenCV来处理图像数据,所以需要学习,搜索了网上的相关资料,整体知识比较零散,花费了较多时间,所以才萌生了将学习过程整理成专栏的形式,希望能帮到后来的人,也方便自己复习。如有错漏欢迎评论或者私信指出,我定当及时更正。
本系列共有上中下三篇,后面有空会再做个小项目,并放出来。
上篇:https://blog.csdn.net/weixin_45703465/article/details/122583084https://blog.csdn.net/weixin_45703465/article/details/122583084
中篇:OpenCV中对图像的处理
下篇:OpenCV中的颜色、形状、人脸和轮廓检测
【OpenCV(C++)快速入门】--下篇--OpenCV中的颜色、形状、人脸和轮廓检测_山海里啊有星辰的博客-CSDN博客
图像的读取是使用OpenCV最最最基本的操作,我们使用如下的方式进行读取。
imread( const String& filename, int flags = IMREAD_COLOR )
//参数解读: filename 文件路径,可以是相对路径也可以是绝对路径。
//IMREAD_COLOR 可以从cv::ImreadModes 中选择不同的读取模式,初学使用默认的就可以,非必须的参数。
OpenCV 对视频的读取使用了VideoCapture 这个类,下面列出了初学常用的几个构造函数。
VideoCapture();//默认的构造函数
VideoCapture(const String& filename);//filename 为需要打开视频的路径
VideoCapture(int index);//如果需要打开本地摄像头,使 index = 0 即可, 插了usb摄像头的话 使用 index =1
无论是视频还是单张图像我们都可以使用下面的函数进行显示:
void imshow(const String& winname, InputArray mat);//参数1 是窗口名称 参数2 需要显示的图像的名称
int waitKey(int delay = 0);
//一般会和imshow()联合使用,否则图像一闪而过,delay 的单位是ms, delay=0代表永远不关闭
下面进行代码的实践,帮助更好的理解。
#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;
}
这里就不放效果图了,自己找张图片和小视频试一下,应该问题不大。
这里介绍几种最最基本的图像处理函数:
// 转换图片的颜色空间(可以把彩色图片转为灰度图)
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() );
void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
//src 为源图像 dst 效果施加后输出的图像--这两个参数含义对本节所列函数都适用
code 为颜色空间的编码,可以在一个枚举变量 ColorConversionCodes 中查到。
dstCn 为输出图像的通道数,默认值为0,也就是默认和源图像保持一致。
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 ,使用这两个参数中的一种即可。
void Canny( InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize = 3, bool L2gradient = false );
//image 为源图像 edges 为检测边缘后输出的图像
threshold1 threshold2 这是两个阈值,通过调节这两个阈值来调节边缘检测的效果。
后面两个参数,初学保持默认就可以。
void dilate( InputArray src, OutputArray dst, InputArray kernel );
kernel 就是上面提到的特点的结构,它本身是 Mat 类型的。使用如下的方式获得:
Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3)); //Size中的数字越大,效果越明显
void erode( InputArray src, OutputArray dst, InputArray kernel );
这里的kernel 同2.2.4。
在接下来的实践中,我们将对下面的图片(图片来自《凡人修仙传》)进行处理。
源代码:
#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;
}
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 缩放比例,小于一为缩小,大于一为放大
这里的裁减指的是获得原始图像的一部分图像,即从原图像上截取一块下来,为了达到这个目的,我们需要先定义一个矩形:
Rect roi(200, 100, 300, 300);
//参数含义:定义该矩形左上角坐标为(200,100),长宽为300x300
然后使用下面的函数即可获得裁减后的图像:
imgCrop = img(roi);//img为原图像
//imgCrop = img(Rect(200,100,300,300)) 也可以
#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;
}
效果如下:
这小节我们简单点,从实践开始:
#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教程写的,这是他的主页,https://www.murtazahassan.com/,有能力的朋友可以去看看。