OpenCV数据载入、显示与保存

一、图像存储器

OpenCV提供了一个Mat类用于存储矩阵数据。Mat类用来保存矩阵类型的数据信息,包括向量、矩阵、灰度或彩色图像等数据。

Mat类分为矩阵头和指向存储数据的矩阵指针的两部分。矩阵头中包含矩阵的尺寸、存储方法、地址和引用次数。矩阵头的大小是一个常数,不随着矩阵尺寸的大小而改变。

创建Mat类:

Mat a;    //创建一个名为a的矩阵头
a = imread("j2.png");//向a中赋值图像数据,矩阵指针指向像素数据
Mat b = a;    //复制矩阵头,并命名为b

从上面的程序可以看出,虽然a和b有各自的矩阵头,但是其矩阵指针指向的矩阵数据是相同的,通过任意一个矩阵头修改矩阵中的数据,另一个矩阵头指向的数据也会随之发生改变。但是,当删除a变量时,b变量并不会指向一个空数据,因为矩阵头中引用次数标记了引用某个矩阵数据的次数,只有当矩阵数据引用次数为0时才会释放矩阵数据。

Mat类可以存储的数据类型包括:double、float、uchar、unsigned char以及自定义的模板等。

声明一个指定类型的Mat类:

Mat A = Mat_<double>(3,3);//创建一个3*3的矩阵用于存放double类型数据

opencv中的数据类型:

数据类型具体类型
CV_8U8位无符号整数
CV_8S8位符号整数
CV_16U16位无符号整数
CV_16S16位符号整数
CV_32S32位符号整数
CV_32F32位浮点整数
CV_64F64位浮点整数

在Opencv中,如果用8位无符号整数存储16位图像,会造成严重的图像颜色失真或造成数据的错误。对于图像来说,只有数据类型是不够的,还需要定义图像数据的通道数,例如灰度图像数据是单通道数据,彩色图像数据是3通道或者4通道数据。因此,opencv定义了通道数标识,C1、C2、C3、C4分别表示单通道、双通道、三通道和四通道。

Mat a(640,480,CV_8UC3);//创建一个640*480的3通道矩阵用于存储彩色图像
Mat b(3,3,CV_8UC1);//创建一个3*3的8位无符号整数的单通道矩阵

1、Mat的赋值

(1)构造时赋值

这种方法是在构造的同时进行赋值,需要注意的是赋值的位数要等于通道数

Mat (int rows
     int cols
     int type
     const Scalar & s 
)
//rows:矩阵的行数
//cols:矩阵的列数
//type:存储数据的类型
//s:给矩阵中每个像素赋值的参考变量

Mat a(2,2,CV_8UC3,Scalar(0,0,255));//创建一个3通道矩阵,每个像素都是0,0,255

(2)、枚举法赋值

这种赋值方式是将矩阵中的所有元素一一列举,并用数据流的形式赋值给Mat类。

Mat a =(Mat_<int>(3,3) << 1,2,3,4,5,6,7,8,9);

(3)、利用数组赋值

float a[8] = {5,6,7,8,1,2,3,4};
Mat b = Mat b = Mat(2,2,CV_32FC2,a);

2、Mat类支持的运算

Mat类变量支持矩阵的加减乘除运算,也可以实现Mat类矩阵的內积和对应位乘法。

需要注意的是,当两个Mat类变量进行加减运算时,必须保证两个矩阵中的数据类型是相同的。

3、Mat类元素的读取

Mat类矩阵在计算机中存储的方式:先存储第一个元素的每个通道的数据,之后再存储第二个元素每个通道的数据。每一行的元素都按照这种方式进行存储。

Mat类矩阵常用的属性:

属性作用
cols矩阵的列数
rows矩阵的行数
step以字节为单位的矩阵的有效宽度
elemSize()每个元素的字节数
total()矩阵中元素的个数
channels()矩阵的通道数

(1)通过at方法读取Mat类矩阵的元素

Mat类数据的读取分为单通道和多通道。

单通道:

Mat a = (Mat_<uchar>(3,3) << 1,2,3,4,5,6,7,8,9);
int value = (int)a.at<uchar>(0,0);

通过at方法读取元素需要在后面跟上“<数据类型>”,如果此处的数据类型与矩阵的数据类型不同,就会出现因数据类型不匹配而产生的报错信息。该方法以坐标的形式给出需要读取的元素坐标(行,列)。

多通道:

在opencv中,针对三通道矩阵,定义了Vec3b、Vec3s、Vec3w、Vec3d、Vec3f、Vec3i共六种类型用于表示同一个元素的3个通道数据;定义中的数字表示通道的个数,最后一位是数据类型的缩写。 b是uchar类型的缩写,s是short类型的缩写,w是ushort类型的缩写,d是double类型的缩写,f是float类型的缩写,i是int 类型的缩写。相应的二通道和四通道的定义也是类似的。

Mat b(3,4,CV_8UC3,Scalar(0,0,1));
Vec3b vc3 = b.at<Vec3b>(0,0);
int first = (int)vc3.val[0];
int second = (int)vc3.val[1];
int third = (int)vc3.val[2];

(2)通过指针ptr读取Mat类矩阵中的元素

Mat b(3,4,CV_8UC3,Scalar(0,0,1));
for(int i=0; i< b.rows ;i++)
{
    uchar* ptr = b.ptr<uchar>(i);
    for(int j=0 ; j< b.cols*b.channels() ; j++)
    {
        cout << (int)ptr[j] << endl;
    }
}

也可以直接通过给出行数和指针后移的位数进行访问,如读取第2行和第3个数据时,可以用a.ptr<uchar>(1)[2]的形式直接访问。

(3)通过迭代器访问Mat类矩阵的元素

Mat类变量同时也是一个容器变量,因此,Mat类变量拥有迭代器。

MatIterator_<uchar> it = a.begin<uchar>();
MatIterator_<uchar> it_end = a.end<uchar>();
for(int i=0 ; it != it_end ; it++)
{
    cout << (int)(*it) << " ";
    if((++i% a.cols) == 0)
    {
        cout << endl;
    }
}

二、图像的读取与显示

1、图像读取函数imread()

函数原型:

imread(const String & filename ,

             int  flags = IMREAD_COLOR

            )

filename:需要读取图像的文件名称,包括图像地址、名称和图像文件扩展名

flags:读取图像形式的标志,如将彩色图像按照灰度图读取、默认参数是按照彩色图像格式读取

函数用于读取指定的图像并将其返回给一个Mat类变量,当图像文件不存在、破损或者格式不受支持时,则无法读取图像,此时函数返回一个空矩阵,因此可以根据返回 矩阵的data属性是否为空或者empty()函数是否为真来判断是否成功读取图像,如果图像读取失败data属性返回值为0,empty()函数返回值为1。

函数读取图像形式参数见下表:

标志参数简记作用
IMREAD_UNCHANGED-1按照原图像读取,保留Alpha通道(第四通道)
IMREAD_GRAYSCALE0将图像转换成单通道灰度图像后读取
IMREAD_COLOR1将图像转换成3通道BGR彩色图像
IMREAD_ANYDEPTH2保留原图像的16位、32位深度,不声明该参数则转成8位读取
IMREAD_ANYCOLOR4以任何可能的颜色读取图像
IMREAD_LOAD_GDAL8使用gdal驱动程序加载图像
IMREAD_REDUCED_GRAYSCALE_216将图像转换为单通道灰度图像,尺寸缩小1/2.可以修改最后一位数字实现缩小1/4和1/8(最后一位数组为4和8)
IMREAD_REDUCED_COLOR_217将图像转换为3通道彩色图像,尺寸缩小1/2.可以修改最后一位数字实现缩小1/4和1/8(最后一位数组为4和8)
IMREAD_IGNORE_ORIENTATION128不以EXIF的方向旋转图像

 

这些标志参数在功能不冲突的情况下可以同时声明多个,不同参数之间用“ | ”隔开。

2、图像窗口函数 namedWindow()

函数原型:
namedWindow(const String & winname

                         int  flags = WINDOW_AUTOSIZE

                        )

winname:窗口名称,用作窗口的标识符

flags :窗口属性设置标志

该函数会创建一个窗口变量,用于显示图像和滑动条,通过窗口的名称引用该窗口,如果在创建窗口时已经存在具有相同名称的窗口,则该函数不会执行任何操作。创建窗口需要占用内存资源,所以在不需要窗口的时候需要关闭窗口来释放内存资源。OpenCV提供了两个关闭窗口的函数:destroyAllWindows()和destroyWindows(),第一个函数是关闭所有窗口,第二个函数关闭指定的窗口。

函数窗口属性标志参数见下表:

标志参数简记作用
WINDOW_NORMAL0x00000000显示图像后,允许用户随意调整窗口大小
WINDOW_AUTOSIZE0x00000001根据图像大小显示窗口,不允许用户调整大小
WINDOW_OPENGL0x00001000创建窗口的时候支持OpenGL
WINDOW_FULLSCREEN1全屏显示窗口
WINDOW_FREERATIO0x00000100调整图像尺寸以充满窗口
WINDOW_KEEPRATIO0x00000000保持图像的比例
WINDOW_GUI_EXPANDED0x00000000创建的窗口允许添加工具栏和状态栏
WINDOW_GUI_NORMAL0x00000010创建没有状态栏和工具栏的窗口

 

默认情况下,函数加载的标志参数为:“WINDOW_AUTOSIZE | WINDOW_KEEPRATIO | WINDOW_GUI_EXPANDED”

3、图像显示函数imshow()

函数原型:

imshow(const String & winname

              InputArray   mat

             )

winname:要显示窗口的名字,用字符串形式赋值

mat:要显示的图像矩阵

该函数会在指定的窗口中显示图像。如果在此函数之前没有创建同名的窗口,就会以WINDOW_AUTOSIZE标志创建一个窗口,显示图像的原始大小;如果创建了图像窗口,那么会缩放图像以适应窗口属性。该函数会根据图像的深度将其缩放,缩放规则如下:

                                   (1)如果图像是8位无符号类型,那么按照原样显示

                                   (2)如果图像是16位无符号类型或者32位整数类型,那么会将像素除以256,将范围由[0,255x256]映射到[0,255]

                                   (3)如果图像是32位或64位浮点类型,那么将像素乘以255,将范围由[0,1]映射到[0,255]

三、视频加载与摄像头调用

1、视频数据的读取VideoCapture()

函数的构造有两种方式:

(1)VideoCapture();

(2)VideoCapture(const String & filename ,

                        int apiPreference = CAP_ANY

                     )

filename :读取的视频文件或者图片系列名称

apiPreference :读取数据时设置的属性,例如编码格式等

第一种方式只是声明了一个能读取视频数据的类,具体读取什么视频文件,需要在使用时通过open()函数指出,例如video.open("1.avi")

第二种方式在构造函数时声明变量并将视频数据赋值给变量。读取图像序列需要将多个图像的名称统一为“前缀+数字”的形式,通过“前缀+%02d”的形式调用(稍后会在代码中体现),也可以使用isOpened()函数判断是否读取成功,成功返回true,失败返回false。

当我们需要使用视频中的图像时,需要将图像由VideoCapture类变量里导出到Mat类变量里,用于后期数据处理,该操作可以通过“>>”运算符将图像按照视频顺序由VideoCapture类变量赋值给Mat类变量,当视频中的所有图像赋值完成后,再次赋值的Mat类变量会变为空矩阵,因此可以通过empty()函数判断是否完成操作。

VideoCapture类变量同时提供了可以查看视频属性的get()函数。

get()方法中的标志参数如下表:

标志参数简记作用
CAP_PROP_POS_MSEC0视频文件的当前位置(以毫秒为单位)
CAP_PROP_FRAME_WIDTH3视频流中图像的宽度
CAP_PROP_FRAME_HEIGHT4视频流中图像的高度
CAP_PROP_FPS5视频流中图像的帧率(每秒帧数)
CAP_PROP_FOURCC6编解码器的4字符代码
CAP_PROP_FRAME_COUNT7视频流中图像的帧数
CAP_PROP_FORMAT8返回的Mat对象的格式
CAP_PROP_BRIGHTNESS10图像的亮度(仅适用于支持的相机)
CAP_PROP_CONTRAST11图像对比度(仅适用于相机)
CAP_PROP_SATURATION12图像饱和度(仅适用于相机)
CAP_PROP_HUE13图像的色调(仅适用于相机)
CAP_PROP_GAIN14图像的增益(仅适用于支持的相机)

2、摄像头的调用VideoCapture()

函数形式:

VideoCapture( int  index ,

                         int  apiPerference = CAP_ANY

                          )

index :要打开的摄像头设备的ID

其他的内容和上面的一样。

举例如下:

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main()
{
	
	/***********************************读取视频********************************/
	
	system("color F0");//更改输出界面颜色
	VideoCapture video("D:/image/j%02d.jpg");	//读取多个图片	//VideoCapture video("E:/OpenCV/learnOpenCV4/data/cup.mp4");//读取视频
	if (video.isOpened())//判断视频读取是否成功
	{
		cout << "视频中图像的宽度=" << video.get(CAP_PROP_FRAME_WIDTH) << endl;
		cout << "视频中图像的高度=" << video.get(CAP_PROP_FRAME_HEIGHT) << endl;
		cout << "视频帧数=" << video.get(CAP_PROP_FPS) << endl;
		cout << "视频总帧数=" << video.get(CAP_PROP_FRAME_COUNT) << endl;
		
	}
	else
	{
		cout << "请输入正确的视频" << endl;
		return -1;
	}
	while (1)
	{
		Mat frame;
		video >> frame;//将图片按照视频顺序由VideoCapture类变量赋值给Mat类变量
		if (frame.empty())//判断是否是否所有图像都已经读取完毕
		{
			break;
		}
		imshow("video", frame);
		waitKey(2000);
	}
	waitKey(0);

/***********************************读取摄像头视频********************************/
/*
	system("color F0");//更改输出界面颜色
	VideoCapture video(0);	//读取摄像头的视频	
	if (video.isOpened())//判断视频读取是否成功
	{
		cout << "视频中图像的宽度=" << video.get(CAP_PROP_FRAME_WIDTH) << endl;
		cout << "视频中图像的高度=" << video.get(CAP_PROP_FRAME_HEIGHT) << endl;
		cout << "视频帧数=" << video.get(CAP_PROP_FPS) << endl;
		cout << "视频总帧数=" << video.get(CAP_PROP_FRAME_COUNT) << endl;
	}
	else
	{
		cout << "请输入正确的视频" << endl;
		return -1;
	}
	while (1)
	{
		Mat frame;
		video >> frame;//将图片按照视频顺序由VideoCapture类变量赋值给Mat类变量
		if (frame.empty())//判断是否是否所有图像都已经读取完毕
		{
			break;
		}
		imshow("video", frame);
		waitKey(1000 / video.get(CAP_PROP_FPS));
	}
	waitKey(0);*/
	destroyAllWindows();
	return 0;

}

四、数据保存

1、图像的保存imwrite()

函数原型:

imwrite( const String & filename,

             InPutArray img,

             Const std::vector<int>& params = std::vector<int>()

            )

filename:保存图像的地址和文件名,包含图像格式

img:将要保存的Mat类矩阵变量

params :保存图片格式属性设置标志

该函数用于将Mat类矩阵保存成图像文件,成功返回true,失败返回false。

不同图像格式能够保存的图像位数如下:

16位无符号(CV_16U)图像可以保存PNG、JPEG、TIFF格式文件

32位浮点(CV_32F)图像可以保存成PFM、TIFF、OpenEXR和RadianceHDR格式文件

4通道(Alpha通道)图像可以保存成PNG格式文件

该函数的第三个参数在一般情况下不需要填写,保存成指定的文件格式只需要直接在第一个参数后面更改文件后缀就可以了,但是当需要保存的Mat类矩阵中数据比较特殊时,则需要设置第三个参数。

第三个参数设置方式:

vector<int> compression_params;
compression_params.push_back(IMWRITE_PNG_COMPRESSION);//png格式图像压缩标志
compression_params.push_back(9);	//设置最高压缩质量
imwrite(filename , img,compression_params);

第三个参数课选择的标志见下表:

标志参数简记作用
IMWRITE_JPEG_QUALITY1保存成JPEG格式的文件的图片质量,分成0~100等级,默认95
IMWRITE_JPEG_PROGRESSIVE2增强JPEG格式,启用为1,默认值为0
IMWRITE_JPEG_OPTIMIZE3对JPEG格式进行优化,启用为1,默认值为0
IMWRITE_JPEG_LUMA_QUALITY5JPEG格式文件单独的亮度质量等级,分成0~100,默认为0
IMWRITE_JPEG_CHROMA_QUALITY6JPEG格式文件单独的色度质量等级,分成0~100,默认为0
IMWRITE_PNG_COMPRESSION16保存成PNG格式文件压缩级别,0~9,值越大意味着更小的尺寸和更长的压缩时间,默认为1(最佳速度设置)
IMWRITE_TIFF_COMPRESSION259保存成TIFF格式文件压缩方案

举例:

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;


void AlphaMat(Mat &mat)
{
	CV_Assert(mat.channels() == 4);//CV_Assert()若括号中的表达式值为false,则返回一个错误信息
	for (int i = 0; i < mat.rows; ++i)
	{
		for (int j = 0; j < mat.cols; ++j)
		{
			Vec4b& bgra = mat.at<Vec4b>(i, j);
			bgra[0] = UCHAR_MAX;	//蓝色通道
			bgra[1] = saturate_cast<uchar>((float(mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX);//绿色通道
			bgra[2] = saturate_cast<uchar>((float(mat.rows - j)) / ((float)mat.rows) * UCHAR_MAX);//红色通道
			bgra[3] = saturate_cast<uchar>(05 * (bgra[1] + bgra[2]));	//Alpha通道
		}
	}
}
int main()
{
	//create mat with alpha channel
	Mat mat(480, 640, CV_8UC4);
	AlphaMat(mat);
	vector<int> compression_params;
	compression_params.push_back(IMWRITE_PNG_COMPRESSION);//png格式图像压缩标志
	compression_params.push_back(9);	//设置最高压缩质量
	bool result = imwrite("D:/image/alpha.png" , mat , compression_params);//bool布尔型,只有一个字节true或者false
	if (!result)
	{
		cout << "保存成PNG失败" << endl;
		return -1;
	}
	cout << "保存成PNG成功" << endl;
	return 0;

}

2、视频的保存VideoWriter()

函数的构造有两种方式:

(1)VideoWriter();

(2)VideoWriter(const String & filename ,

                               int  fource,

                              double fps,

                              Size frameSize,

                              bool isColor=true

                     )

filename :保存视频的地址和文件名,包含视频格式

fource:压缩帧的4字符编解码器代码

fps:保存视频的帧率,即视频中每秒图像的张数

frameSize:视频帧的尺寸

isColor:保存视频是否为彩色视频

第一种构造函数的使用方法与VideoCapture() 相同,都是创建一个用于保存视频的数据流,后续通过open()函数设置保存文件名称、编解码器、帧数等。

第二种构造函数的用法和VideoCapture()的第二种方式创建的函数相同 ,可以使用isOpened()函数判读是否成功创建一个视频流,可以通过get()查看视频流中的属性。

在保存视频时,需要将生成视频的图像一帧一帧地通过“<<”操作符(或者write()函数)赋值给视频流,最后使用release()关闭视频流。

视频编码格式:

OpenCV4.1版本标志作用
VideoWriter::fourcc('D', 'I', 'V', 'X')MPEG-4编码
VideoWriter::fourcc('P', 'I', 'M', '1')MPEG-1编码
VideoWriter::fourcc('M', 'J', 'P', 'G')JPEG编码
VideoWriter::fourcc('M', 'P', '4', '2')MPEG-4.2编码
VideoWriter::fourcc('D', 'I', 'V', '3')MPEG-4.3编码
VideoWriter::fourcc('U', '2', '6', '3')H263编码
VideoWriter::fourcc('I', '2', '6', '3')H263I编码
VideoWriter::fourcc('F', 'L', 'V', '1')FLV1编码

举例:

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	Mat img;	
	VideoCapture video(0);  //使用某个摄像头
	//读取视频
	//VideoCapture video;
	//video.open("D:/image/j%02d.jpg");  

	if (!video.isOpened())  // 判断是否调用成功
	{
		cout << "打开摄像头失败,请确实摄像头是否安装成功";
		return -1;
	}

	video >> img;  //获取图像
				   //检测是否成功获取图像
	if (img.empty())   //判断有没有读取图像成功
	{
		cout << "没有获取到图像" << endl;
		return -1;
	}
	bool isColor = (img.type() == CV_8UC3);  //判断相机(视频)类型是否为彩色

	VideoWriter writer;
	int codec = VideoWriter::fourcc('M', 'J', 'P', 'G');  // 选择编码格式
														  //OpenCV 4.0版本设置编码格式
														  //int codec = CV_FOURCC('M', 'J', 'P', 'G'); 

	double fps = 0.5;  //设置视频帧率 
	string filename = "D:/image/live.avi";  //保存的视频文件名称
	writer.open(filename, codec, fps, img.size(), isColor);  //创建保存视频文件的视频流

	if (!writer.isOpened())   //判断视频流是否创建成功
	{
		cout << "打开视频文件失败,请确实是否为合法输入" << endl;
		return -1;
	}

	while (1)
	{
		//检测是否执行完毕
		if (!video.read(img))   //判断能都继续从摄像头或者视频文件中读出一帧图像
		{
			cout << "摄像头断开连接或者视频读取完成" << endl;
			break;
		}
		writer.write(img);  //把图像写入视频流
							//writer << img;
		imshow("Live", img);  //显示图像
		char c = waitKey(1000);
		if (c == 27)  //按ESC案件退出视频保存
		{
			break;
		}
	}
	// 退出程序时刻自动关闭视频流
	//video.release();
	//writer.release();	
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MFC(Microsoft Foundation Classes)是Microsoft公司开发的一个用于Windows应用程序开发的C++类库。它提供了一个图形用户界面(GUI)框架,使开发人员可以创建Windows应用程序。OpenCV(Open Source Computer Vision)是一个开源的计算机视觉库,它支持各种图像处理和计算机视觉算法,包括图像处理、高级计算机视觉、机器学习、目标检测和跟踪等。 MFC和OpenCV可以一起使用来开发Windows图像处理应用程序。MFC提供了图形界面,可以让用户与程序进行交互;而OpenCV提供了强大的图像处理和计算机视觉功能,可以对图像进行分析和处理。使用MFC和OpenCV结合起来可以让开发人员轻松地创建一个功能强大的图像处理程序。 在使用MFC和OpenCV开发图像处理应用程序时,开发人员需要熟悉MFC和OpenCV的相关知识,掌握MFC的Windows编程和OpenCV的图像处理能力。开发人员可以使用MFC的窗口、对话框和控件等创建图形界面,然后使用OpenCV来进行图像的读取、处理和输出等操作。开发人员需要在开发过程中注意MFC和OpenCV的相互调用关系,使得程序可以正确运行。 总之,MFC和OpenCV是两个强大的工具,它们可以一起使用来开发图像处理应用程序。在使用MFC和OpenCV开发图像处理应用程序时,开发人员需要熟悉它们的相关知识并合理地运用它们的功能,才能开发出高效、易用、功能强大的应用程序。 ### 回答2: MFC是Microsoft Foundation Class的缩写,是Windows操作系统上的一个GUI应用程序框架,可以帮助开发者快速地创建窗口和用户界面。而OpenCV是一个流行的开源计算机视觉库,可以用于图像处理、模式识别、物体跟踪等方面。由于MFC和OpenCV都是针对Windows系统的开发,因此结合使用这两个工具可以方便地实现图像处理和GUI设计的功能。 通过MFC,开发者可以创建一个具有图形界面的应用程序,然后与OpenCV结合可以实现图像处理的各种功能,例如图像滤波,图像分割,特征提取等。通过这种方法,开发者可以快速且方便地开发出图像处理软件,而且可以为MFC界面添加很多可以增强用户体验的控件。 举个例子,假设我们要设计一个用于人脸识别的软件,我们可以使用MFC创建一个简单的用户界面,然后通过OpenCV提供的人脸检测算法来实现人脸识别功能。在这个软件中,OpenCV将负责图像处理和人脸检测部分,而MFC将负责用户界面的设计和数据输入输出。 总之,MFC和OpenCV的结合可以为Windows下的图像处理软件开发提供很大的便利,可以满足很多应用程序的需求。 ### 回答3: MFC是Microsoft Foundation Class的缩写,是微软公司针对Windows操作系统开发的应用程序框架。它提供了许多可重用的类,用于简化Windows应用程序的开发过程。而OpenCV是一种开源计算机视觉库,提供了许多图像处理和计算机视觉算法及工具,可以用于实现包括人脸检测、图像识别等多种应用。它的优势在于它的代码简洁易懂,易于学习,同时也提供了Python、C++等多种编程语言的接口。 使用MFC和OpenCV4相结合可以实现很多图像处理的应用,比如图像的读入、载入、预处理、显示等等,可以非常方便的实现对图像的各种操作。另外,MFC框架可以提供一些Windows操作系统的API,用于支持与系统交互的功能,比如打开选择文件框、保存文件框等等。结合OpenCV和MFC的图像处理应用可以方便的实现这些操作和一些自定义的交互界面。 总之,MFC和OpenCV4的结合可以方便、高效的实现计算机视觉领域的图像处理应用程序,为人工智能和机器视觉等领域提供了很好的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值