Prepare for OpenCV

"OpenCV in Ubuntu/C++"

Posted by slef's visitor on September 15, 2025

文档前置说明

文本首先学习了一篇大佬的博客,但是emm大佬教的可能不能很好适配我的工作。所以为了强化技能,又学习了另一个OpenCV一些基础操作以及操作原理,处理效果。 来自于b站上转载的一个课程

原视频地址

b站转载

基础数据结构与图片读取展示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using nameplaces std;
using nameplaces cv;

Mat img = cv.imread(img_path);
#保证代码健壮性
if(img.empty()){
    cout<<"img not found"<<endl;
    return -1;
}
namedWindow("window_name",WINDOW_FREERATIO);
imshow("window_name",img);
waitKey(0);  #等待多少ms
destoryAllWindows();

VideoCapture capture(0);
if(!capture.isOpened()){

    }

VedioWriter writer;
writer.open(img_path,
            VideoWriter::fourcc('M','J','P','G'),
            25,
            Size(frame.cols,frame.rows));
while(1){
    capture >> frame ;
    writer.write(frame);
    imshow("video_demo",frame);
    if(waitKey(30)==27){
        break;
    }
}
writer.release();
imread()

在介绍imread()之前,我觉得有必要了解一下图片处理,以及基本图像视觉的知识。

  • 模拟图像 又称连续图像,具有灰度值
  • 数字图像 由模拟图像数字化得到,通常用一个二维数组表示,f(x,y),f常用来表示灰度值等性质
  • 颜色模式(颜色储存)
    • 色相
    • 明度
    • 饱和度 常分为RGB,CMYK,HSB,Lab,位图,灰度,索引颜色,双色调,多通道等模式
  • 色彩模式(显示方式) 人们通常把颜色分为不同分量来显示颜色。
  • 二值图像 只有黑白即0,1两种颜色
  • 灰度图像 一般灰度取值为unsigned int,仅仅只有256个值
  • 索引颜色图像 颜色一般都是预定义的,可供选用的一组颜色也是有限的。

颜色格式:

  • BGR
  • Grayscale
  • HSV 色相,饱和度,明度 (实时性较差)
  • HSB 色度,饱和度,亮度(OpenCV支持较少)
  • YCrCb 亮度,红色差,蓝色差
  • Lab 名度,a通道,b通道(实时性较差)

IMREAD_UNCHANGED :读取原图像,包括alpha通道(alpha通道表示图片的2透明度)png支持透明度,而jpg不支持 IMREAD_GRAYSCALE :以灰度值读取图像。适用于只需要亮度信息的场景,如:边缘检测,字符识别,可以减少数据量并简化处理 IMREAD_COLOR : 以彩色图像读取(默认)。使用与大多数需要处理色彩信息的场景 IMREAD_ANYDEPTH : 以原图像深度读取。如果图像是16或32位深度,则会保持 IMREAD_ANYCOLOR : 以任意可能的颜色格式读取图像,具体格式有图片自身决定,自动选择 IMREAD_LOAD_GDAL :使用地理数据抽象库来读取图像,主要用于处理遥感图像,地理信息相关的特殊图片格式 IMREAD_REDUCED_GRAYSCALE_2 : 读取灰度并缩小尺寸为原来的1/2。获取低分辨率的灰度图,用来快速预览或减少计算量。 IMREAD_REDUCED_COLOR_2 : IMREAD_REDUCED_GRAYSCALE_4 :

1
2
3
Mat img = imread("img_path",IMREAD_GRAYSCALE)
imshow("img_gray",img);
imwrite("save_path",img)
1
2
3
4
5
Mat mask,hsv;
Mat img = imread("img_path");
cvtColor(img,hsv,COLOR_BGR2HSV);
inRange(hsv,Scalar(0,43,46),Scalar(10,255,255),mask);
imshow("mask",mask);
Mat数据对象及一般操作
1
2
3
4
5
6
7
8
9
Mat m1 = zeros(3,3,CV_8UC3)
int width = m1.rows;
int height = m1.cols;
int channels = m1.channels();
m1 = m1 - Scalar(100,10,1);

//当进行像素值操作后,有些值超过了255(对于8位图像,像素值的范围是0到255)时,可以选择进行饱和操作(saturate),将超过范围的值强制截断到合法范围内。
Mat saturated_img;
staurate_cast(m1,saturated_img);
类型转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cvtColor(img,img_gray,COLOR_BGR2GRAY);//灰度化
//归一化
normalize(img_gray,img_dst,0,255,NORM_MINMAX,CV_8UC1);
//dst(x,y) = (src(x,y) - min_val) * (beta - alpha) / (max_val - min_val) + alpha

//缩放
resize(img,img_dst,Size(x,y),0,0,INTER_LINEAR);
//翻转
flip(img,img_dst,filpCode);
//filpCode=0 绕x旋转,>0绕y旋转,<0绕x和y同时翻转
//旋转,这个有点困难,暂时留下




OI操作
1
2
3
4
5
6
7
8
9
10
11
//TrackBar滚动条 
createTrackbar("trackbar_name","trackerbar_window_name",);
//键盘响应
int key = waitKey();
if(key==1){
    cout<<"我是hzy"<<endl;
}

//鼠标操作与响应
setMouseCallback("mouse_demo",on_mouse,(void*)(&img));
//  这个函数有一点难以理解,可以先放着
一些操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//颜色映射
int colorMap[] = {
	COLORMAP_AUTUMN, COLORMAP_BONE,
	COLORMAP_JET, COLORMAP_WINTER,
	COLORMAP_RAINBOW, COLORMAP_OCEAN,
	COLORMAP_SUMMER, COLORMAP_SPRING,
	COLORMAP_COOL, COLORMAP_HSV,
	COLORMAP_PINK, COLORMAP_HOT
	};
applyColorMakp(img,dst,colorMap[num]);
//将img根据colormap中的颜色映射规则,转为dst

//位操作
Mat m1 = zeros(Size(256,256),CV_8UC3);
Mat m2 = zeros(Size(256,256),CV_8UC3);
Mat dst_and,dst_or,dst_not,dst_xor;
bitwise_and(m1,m2,dst_and);
bitwise_or(m1,m2,dst_or);
bitwise_not(m1,m2,dst_not);
bitwise_xor(m1,m2,dst_xor);

//通道分离
split(img,bgr);
//bgr就是我们想要的目标数组
bgr[1] = 0 ;//green通道置为0
merge(bgr,3,dst);
//合并到dst

//混合图像
addWeighted(src1,ratio_1,src2,ratio_2,norm_num,dst2);
//计算方式:src1*ratio_1+src*ratio_2+norm_num

//像素值统计、
split(img,bgr)
minMaxLoc(bgr[1],minVal,maxVal,minLoc,maxLoc);//找到单通道中像素的最值以及它们的位置
meanStdDev(img,mean,stddev);
//计算所有像素的均值和方差

几何形状绘制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Mat img = zeros(Size(512,512),CV_8U3C);
img = Scalar(255,255,255);

//line()
line(img,Point(100,100),Point(200,200),Scalar(0,0,255),2,LINE_8,0);
//img 起点 终点 颜色 宽度 线型 坐标点缩放比例
//rectangle()
rectangle(img,Rect(200,200,100,100),Scalar(255,255,0),2,LINE_8,0);
//img Rect(左上角x,y,右下角x,y) 颜色 线宽 线型 坐标点缩放比例
//circle()
circle(img,Point(300,300),50,Scalar(255,0,0),2,LINE_8,0);
//img 圆心x,y 半径 颜色 线宽 线型 坐标点缩放比例
//ellipse()
ellipse(img,Point(400,400),Size(100,50),0,0,360,Scalar(0,0,255),2,LINE_8,0);
//img 圆心 长轴短轴 旋转角度 绘制范围begin end 颜色 线宽 线型 坐标点缩放比例 
//fillPoly()
vector<Point> points;
points.push_back(Point(100,400));
points.push_back(Point(200,300));
points.push_back(Point(300,400));
points.push_back(Point(400,300));
points.push_back(Point(500,400));
//fillPoly()本是用来绘制(填充)多个多边形,所以当我们只有一个多边形的时候,应该是转为vector Point<Point>
const Point* pts[1] =  {points.data()};
int pt_num[] = {points.size()};
fillPoly(img,pts,pt_num,1,Scalar(0,255,255),LINE_8,0);
//img points数组 pt数量 绘制多边形的数量 颜色 线型 坐标点缩放比例  (因为这里是填充fill,所以没有线宽这个参数)

//随机数与随机颜色
RNG rng(seed_num);
//需要给一个种子值,如果不给种子值,默认为某一个种子值,不管怎样跑出来的固定的一个随机数列。
//如果真的想搞随机,可以直接#include <time.h> 使用time(0)来当种子值



直方图
1
//饶了我吧
卷积
1
2
3
Mat kernel = (Mat_<float>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
Mat dst;
filter2D(img,dst,-1,keneral);