C/C++开发,opencv读写图像函数详解

news2024/11/25 18:53:11

目录

一、cv::imread函数读取图像

        1.1 imread函数

        1.2 imread函数的参数解析

        1.3  imread函数实践案例

        1.4 编译及测试

 二、cv::imwrite函数存储图像

        2.1 cv::imwrite函数

        2.2 imwrite函数参数解析

        2.3 imwrite函数实践案例

        2.4 编译及测试


一、cv::imread函数读取图像

        1.1 imread函数

        函数imread从指定的文件中加载图像并返回。如果无法读取图像(因为缺少文件、权限不正确、格式不受支持或无效),该函数将返回一个空矩阵(Mat::data==NULL)。

        imread函数的声明如下:

//imgcodes.hpp

namespace cv
{
CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR );
};

        1.2 imread函数的参数解析

        cv::imread函数第一个参数(filename)是图片名,该图片名可以是完整路径,也可以是相对路径(以当前路径为基准)。使用cv::imread()从磁盘中读取一张图片时,cv::imread()并不关心文件的拓展名是什么(注:读者可以将图片名后缀去掉,然后再读取,观察imread函数加载图片情况,也可以进一步指定组合flag来进一步验证),而是分析文件中前几个字节(被称为文件的识别标识或者“魔法序列”)来确定图像的编码格式。

        目前,imread函数支持以下文件格式:

-Windows位图-\*.bmp,\*.dib
-JPEG文件-\*.JPEG、\*.jpg、\*.jpe
-JPEG 2000文件-\*.jp2
-可移植网络图形-\*.png
-WebP-\*.WebP
-可移植图像格式-\*.pbm、\*.pgm、\*.ppm\*.pxm、\*.pnm
-PFM文件-\*.PFM
-sr文件-\*.sr,\*.ras
-TIFF文件-\*.TIFF、\*.tif
-OpenEXR图像文件-\*.exr
-Radiance HDR-\*.HDR,\*.pic
-GDAL支持的光栅和矢量地理空间数据

        第二个参数flags可以被设置为下面的任意一个值。默认情况下,flags被设置为Cv::IMREAD_COLOR。

Cv::IMREAD_COLOR		总是读取三通道图像
Cv::IMREAD_GRAYSCALE	总是读取单通道图像 
CV::IMREAD_ANYCOLOR		通道数由文件实际通道数(不超过3)
Cv::IMREAD_ANYDEPTH		允许加载超过8bit深度。
Cv::IMREAD_UNCHANGED	等于将Cv::IMREAD_ANYCOLOR和CV::IMREAD_ANYDEPTH组合了起来。

        这个值表示图片将被以三通道8位的格式读取。在这种情况下,即便原始文件中的图像是灰度图像,读取到内存中的仍然有三通道,每个通道拥有相同数据的图像。如果flags被设置为Cv::IMREAD_GRAYSCALE,那么不管文件内部图像是几通道,图片都以灰度图像的格式加载。flags的另外一个值是Cv::IMREAD_ANYCOLOR。在此种情况下,图片的载入方式取决于其内部图像的具体情况,如果是彩色图像,就以三通道注2的形式载入,如果是灰度图像,则按照单通道的形式载入。

        这些flags的定义来自于ImreadModes枚举类型:

//imgcodes.hpp

namespace cv{
//! Imread flags
enum ImreadModes {
IMREAD_UNCHANGED=-1,//按原样返回加载的图像(使用alpha通道,否则会被裁剪)。忽略EXIF方向。

IMREAD_GRAYSCALE=0,//始终将图像转换为单通道灰度图像(编解码器内部转换)。

IMREAD_COLOR=1,//!始终将图像转换为3通道BGR彩色图像。

IMREAD_ANYDEPTH=2,//在输入具有相应深度时返回16位/32位图像,否则将其转换为8位。

IMREAD_ANYCOLOR=4,//以任何可能的颜色格式读取图像。

IMREAD_LOAD_GDAL=8,//使用gdal驱动程序加载图像。

IMREAD_REDUCED_GRAYSCALE_2=16,//始终将图像转换为单通道灰度图像,并将图像大小缩小1/2。

IMREAD_REDUCED_COLOR_2=17,//始终将图像转换为3通道BGR彩色图像,并将图像大小缩小1/2。

IMREAD_REDUCED_GRAYSCALE_4=32,//始终将图像转换为单通道灰度图像,并将图像大小缩小1/4。

IMREAD_REDUCED_COLOR_4=33,//始终将图像转换为3通道BGR彩色图像,并将图像大小缩小1/4。

IMREAD_REDUCED_GRAYSCALE_8=64,//始终将图像转换为单通道灰度图像,并将图像大小缩小1/8。

IMREAD_REDUCED_COLOR_8=65,//始终将图像转换为3通道BGR彩色图像,并将图像大小缩小1/8。

IMREAD_IGNORE_ORIENTATION=128//不要根据EXIF的方向标志旋转图像。 
     };
};

        可以看到ImreadModes是按位定义的一个数值,意味着该参数可以通过"|"组合的方式构建实参。

        1.3  imread函数实践案例

        imread函数的调用很简单,主要就传入文件名及读取flags参数,返回一个mat对象,如果成功该对象非空就表示读取成功。

cv::Mat img = cv::imread(文件名.支持图像后缀,flag1|flag2|...)

        本文编写一个读取.png图片的案例,通过不同的ImreadModes值读取一个png格式图片,创建一个文件目录show_img5,创建文件main.cpp和Makefile文件,其中main.cpp如下,通过不同的flag读取一个图片,并调用HighGUI模块的cv::imshow函数显示图片:

#include "opencv2/opencv.hpp" //Include file for every supported OpenCV function 
#include <iostream>

int main( int argc,char** argv )
{
	cv::Mat img_rgb,img_gry,img_any,img_dep,img_unc;
	cv::namedWindow("Example RGB", cv::WINDOW_AUTOSIZE );
	cv::namedWindow("Example GRY", cv::WINDOW_AUTOSIZE );
	cv::namedWindow("Example ANY", cv::WINDOW_AUTOSIZE );
	cv::namedWindow("Example DEP", cv::WINDOW_AUTOSIZE );
	cv::namedWindow("Example UNC", cv::WINDOW_AUTOSIZE );

	//
	img_rgb=cv::imread( argv[1],cv::IMREAD_COLOR);
	if( !img_rgb.empty() ) 	cv::imshow("Example RGB",img_rgb );
	//
	img_gry=cv::imread( argv[1],cv::IMREAD_GRAYSCALE);
	if( !img_gry.empty() ) 	cv::imshow("Example GRY",img_gry );
	//
	img_any=cv::imread( argv[1],cv::IMREAD_ANYCOLOR);
	if( !img_any.empty() ) 	cv::imshow("Example ANY",img_any );
	//
	img_dep=cv::imread( argv[1],cv::IMREAD_ANYDEPTH);
	if( !img_dep.empty() ) 	cv::imshow("Example DEP",img_dep );
	//
	img_unc=cv::imread( argv[1],cv::IMREAD_UNCHANGED);
	if( !img_unc.empty() ) 	cv::imshow("Example UNC",img_unc );

	cv::waitKey(0);
	return(0);
}

        工程组织Makefile文件如下(本文是采用win下MinGW方式编译的,如何搭建opencv库+MinGW编译的请参考本专栏的opencv库安装编译博文)。

#/bin/sh
CX= g++ 

BIN 		:= ./
TARGET      := show_img5.exe
FLAGS		:= -std=c++11 -static
SRCDIR 		:= ./
#INCLUDES
INCLUDEDIR 	:= -I"../../opencv_MinGW/include" 
#-I"$(SRCDIR)"
staticDir   := ../../opencv_MinGW/x64/mingw/staticlib/
#LIBDIR		:= $(staticDir)/libopencv_world460.a\
#			   $(staticDir)/libade.a \
#			   $(staticDir)/libIlmImf.a \
#			   $(staticDir)/libquirc.a \
#			   $(staticDir)/libzlib.a \
#			   $(wildcard $(staticDir)/liblib*.a) \
#			   -lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 
#opencv_world放弃前,然后是opencv依赖的第三方库,后面的库是MinGW编译工具的库

LIBDIR 	    := -L $(staticDir) -lopencv_world460 -lade -lIlmImf -lquirc -lzlib \
				-llibjpeg-turbo -llibopenjp2 -llibpng -llibprotobuf -llibtiff -llibwebp \
				-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 
source		:= $(wildcard $(SRCDIR)/*.cpp) 

$(TARGET) :
	$(CX) $(FLAGS) $(INCLUDEDIR) $(source)  -o $(BIN)/$(TARGET) $(LIBDIR)

clean:
	rm  $(BIN)/$(TARGET)

        1.4 编译及测试

        进入show_img5目录,make -j*编译案例,如下:

        进入该目录命令行运行编译输出程序

show_img5.exe 1.PNG

 二、cv::imwrite函数存储图像

        2.1 cv::imwrite函数

        cv::imwrite函数与cv::imread函数相对,形成互补关系。

//imgcodes.hpp

namespace cv
{
CV_EXPORTS_W bool imwrite( const String& filename, InputArray img,
              const std::vector<int>& params = std::vector<int>());
};

        函数imwrite将图像保存到指定的文件中。图像格式是根据文件扩展名选择的。通常,使用此功能只能保存8位单通道或3通道(具有“BGR”通道顺序)图像,但以下情况除外:

-在PNG、JPEG 2000和TIFF格式的情况下,可以保存16位无符号(CV_16U)图像

-32位浮点(CV_32F)图像可以保存为PFM、TIFF、OpenEXR和Radiance HDR格式;将使用LogLuv高动态范围编码保存3通道(CV_32FC3)TIFF图像(每个像素4个字节)

-使用此功能可以保存带有alpha通道的PNG图像。要执行此操作,请创建8位(或16位)4通道图像BGRA,其中alpha通道最后到达。完全透明的像素应将alpha设置为0,完全不透明的像素应将alpha设置为255/65535。

-多个图像(Mat的矢量)可以保存为TIFF格式。

        2.2 imwrite函数参数解析

        第一个参数给定了文件名,文件名的拓展名部分用来决定以何种格式保存图像,以下是一些OpenCV支持的常用拓展名:

[1] jpg或者jpeg:以baseline JPEG格式保存;8位数据;单通道或三通道输入;
[2] jp2:JPEG2000;8位或者16位数据;单通道或三通道输入;
[3] tif或者.tiff:TIFF;8位或者16位数据;单通道、三通道或四通道输入
[4] png:PNG;8位或者16位数据;单通道、三通道或四通道输入
[5] bmp:BMP;8位数据;单通道、三通道或四通道输入
[6] ppm,.pgm:NetPBM;8位数据;单通道(PGM)或者三通道(PPM)

        如果不支持图像格式,则图像将转换为8位无符号(CV_8U)并以这种方式保存。如果格式、深度或通道顺序不同,使用Mat::convertTo和cv::cvtColor在保存前进行转换。或者,使用通用FileStorage I/O函数将图像保存为XML或YAML格式。

        第二个参数是待存储的输入图像。

        第三个参数被用作特殊类型文件的写入操作时所需的数据。输入参数为内部为整型数据的一个STL vector,vector中的整型序列的具体内容为:一系列的参数ID,以及与该参数对应的参数值,每个参数ID之后跟着其对应的值,默认为空数组。

params格式化编码为对的特定参数:
vector<int> args(paramId_1, paramValue_1, paramId_2, paramValue_2, …)

        这些写入标记flag是一个枚举值类型:

//imgcodes.hpp

namespace cv
{
//! Imwrite flags
enum ImwriteFlags {
IMWRITE_JPEG_QUALITY=1,//JPEG,它可以是从0到100的质量(越高越好)。默认值为95。

IMWRITE_JPEG_PROGRESSIVE=2,//启用JPEG功能,0或1,默认值为False。

IMWRITE_JPEG_OPTIMIZE=3,//启用JPEG功能,0或1,默认值为False。

IMWRITE_JPEG_RST_INTERVAL=4,//JPEG重新启动间隔,0-65535,默认为0-不重新启动。

IMWRITE_JPEG_LUMA_QUALITY=5,//单独的亮度质量级别,0-100,默认为-1-不使用。

IMWRITE_JPEG_CHROMA_QUALITY=6,//单独的色度质量级别,0-100,默认为-1-不使用。

IMWRITE_JPEG_SAMPLING_FACTOR=7,//对于JPEG,请设置采样因子。见cv::ImwriteJPEGSamplingFactorParams。

IMWRITE_PNG_COMPRESSION=16,//对于PNG,它可以是从0到9的压缩级别。值越高,表示尺寸越小,压缩时间越长。如果指定了策略,则策略将更改为IMWRITE_PNG_TSTRATIY_DEFAULT(Z_DEFAULT_strategy)。默认值为1(最佳速度设置)。

IMWRITE_PNG_STRATEGY=17,//其中一个cv::ImwritePNGFlags,默认为IMWRITE_PNG_STRATEGY_RLE。

IMWRITE_PNG_BILEVEL=18,//二进制级别PNG,0或1,默认值为0。

IMWRITE_PXM_BINARY=32,//对于PPM、PGM或PBM,它可以是二进制格式标志,0或1。默认值为1。

IMWRITE_EXR_TYPE=(3<<4)+0,/*48*//超控EXR存储类型(默认为浮动(FP32)),见cv::ImwriteEXRTypeFlags

IMWRITE_EXR_COMPRESSION=(3<<4)+1,/*49*//覆盖EXR压缩类型(默认为ZIP_compression=3),见cv::ImwriteEXRCompressionFlags

IMWRITE_WEBP_QUALITY=64,//对于WEBP,它可以是从1到100的质量(越高越好)。默认情况下(没有任何参数),并且对于高于100的质量,使用无损压缩。

IMWRITE_PAM_TUPLETYPE=128,//对于PAM,将TUPLETYPE字段设置为为该格式定义的相应字符串值,见cv::ImwritePAMFlags

IMWRITE_TIFF_RESUNIT=256,//对于TIFF,用于指定要设置的DPI分辨率单位;有关有效值,请参阅libtiff文档

IMWRITE_TIFF_XDPI=257,//对于TIFF,使用指定X方向DPI

IMWRITE_TIFF_YDPI=258,//对于TIFF,使用指定Y方向DPI

IMWRITE_TIFF_COMPRESSION=259,//对于TIFF,使用指定图像压缩方案。有关压缩格式对应的整数常量,请参见libtiff。注意,对于深度为CV_32F的图像,仅使用libtiff的SGILOG压缩方案。对于其他支持的深度,可以通过该标志指定压缩方案;LZW压缩是默认设置。

IMWRITE_JPEG2000_compressionx1000=272//对于JPEG2000,使用指定目标压缩率(乘以1000)。该值可以在0到1000之间。默认值为1000。
     };
};

        cv::imwrite()是为图像文件定制的,它非常依赖那些用于处理图像文件的库。这些库通常被叫做codecs。很多的操作系统应该已经拥有很多编码解码库,即使没有全部编解码库,但至少对于常见的格式,每一种类型的图片都应该有一个可以使用的编解码库。
        OpenCV对一些图片格式(例如JPEG、PNG、TIFF等)自带用于编码解码库。对于这些编解码库,可以有以下三种选择:a)不使用这些编解码库;b)使用OpenCV所提供的编解码库(记得与其他OpenCV模块一起编译);c)使用相应的拓展库(例如libjpeg、libpng等)。在Windows系统中,默认是b选项。在OS X/Linux系统上,默认选项是c;如果Cmake无法发现编解码库,就使用选项b。可以显式指定所需要的选项。

        2.3 imwrite函数实践案例

        本文编写一个读取某.png图片,然后按各自图片格式另存该图像数据,创建一个文件目录show_img6,创建文件main.cpp和Makefile文件,其中main.cpp如下,通过不同的图片名后缀来明确存储图片的文件格式,另外可以另行制定写入图片的flag,采用vector<int>数组容器来设置:

#include "opencv2/opencv.hpp" //Include file for every supported OpenCV function 
#include <iostream>

using namespace std;

int main( int argc,char** argv )
{
	//图片数据载入
	cv::Mat img_rgb,img_gry;
	img_rgb=cv::imread( argv[1]);
	cv::cvtColor( img_rgb,img_gry,cv::COLOR_BGR2GRAY);//转灰度图
	//
	bool ret = false;
	ret = cv::imwrite("2.jpg",img_rgb);//保存图片.jpg
	if(ret)
	{
		cout <<"success save 2.jpg"<< endl;
	}
	ret = cv::imwrite("3.jpeg",img_rgb);//保存图片.jpeg
	if(ret)
	{
		cout <<"success save 3.jpeg"<< endl;
	}
	ret = cv::imwrite("4.jp2",img_rgb);//保存图片.jp2
	if(ret)
	{
		cout <<"success save 4.jp2"<< endl;
	}
	ret = cv::imwrite("5.tif",img_rgb);//保存图片.tif
	if(ret)
	{
		cout <<"success save 5.tif"<< endl;
	}
	ret = cv::imwrite("6.tiff",img_rgb);//保存图片.tiff
	if(ret)
	{
		cout <<"success save 6.tiff"<< endl;
	}
	ret = cv::imwrite("7.png",img_rgb);//保存图片.png
	if(ret)
	{
		cout <<"success save 7.png"<< endl;
	}
	ret = cv::imwrite("8.bmp",img_rgb);//保存图片.bmp
	if(ret)
	{
		cout <<"success save 8.bmp"<< endl;
	}
	ret = cv::imwrite("9.ppm",img_rgb);//保存图片.ppm
	if(ret)
	{
		cout <<"success save 9.ppm"<< endl;
	}

	ret = cv::imwrite("10.pbm",img_gry);//保存图片.pbm
	if(ret)
	{
		cout <<"success save 10.pbm"<< endl;
	}
	vector<int> w_args_02; 
	w_args_02.push_back(cv::IMWRITE_PXM_BINARY);
	w_args_02.push_back(0);
	ret = cv::imwrite("10_1.pbm",img_gry,w_args_02);//保存图片.pbm
	if(ret)
	{
		cout <<"success save 10_1.pbm"<< endl;
	}
	ret = cv::imwrite("11.pgm",img_gry);//保存图片.pgm
	if(ret)
	{
		cout <<"success save 11.pgm"<< endl;
	}
	ret = cv::imwrite("11_1.pgm",img_gry,w_args_02);//保存图片.pgm
	if(ret)
	{
		cout <<"success save 11_1.pgm"<< endl;
	}
	// cv::waitKey(0);
	return(0);
}

        工程组织Makefile文件和前面读取图片的案例几乎一致,仅仅改动了输出功能名,如下(本文是采用win下MinGW方式编译的,如何搭建opencv库+MinGW编译的请参考本专栏的opencv库安装编译博文)。

#/bin/sh
CX= g++ 

BIN 		:= ./
TARGET      := show_img6.exe
FLAGS		:= -std=c++11 -static
SRCDIR 		:= ./
#INCLUDES
INCLUDEDIR 	:= -I"../../opencv_MinGW/include" 
#-I"$(SRCDIR)"
staticDir   := ../../opencv_MinGW/x64/mingw/staticlib/
#LIBDIR		:= $(staticDir)/libopencv_world460.a\
#			   $(staticDir)/libade.a \
#			   $(staticDir)/libIlmImf.a \
#			   $(staticDir)/libquirc.a \
#			   $(staticDir)/libzlib.a \
#			   $(wildcard $(staticDir)/liblib*.a) \
#			   -lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 
#opencv_world放弃前,然后是opencv依赖的第三方库,后面的库是MinGW编译工具的库

LIBDIR 	    := -L $(staticDir) -lopencv_world460 -lade -lIlmImf -lquirc -lzlib \
				-llibjpeg-turbo -llibopenjp2 -llibpng -llibprotobuf -llibtiff -llibwebp \
				-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 
source		:= $(wildcard $(SRCDIR)/*.cpp) 

$(TARGET) :
	$(CX) $(FLAGS) $(INCLUDEDIR) $(source)  -o $(BIN)/$(TARGET) $(LIBDIR)

clean:
	rm  $(BIN)/$(TARGET)

        2.4 编译及测试

        进入show_img6目录,make -j*编译案例,如下:

         进入该目录命令行运行编译输出程序:

show_img6.exe 1.PNG

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/608632.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Lecture 5 Part of Speech Tagging

目录 POS application: Information Extraction 词性应用&#xff1a;信息提取 POS Open Class 开放类词性Problem of word classes: Ambiguity 词类问题&#xff1a;模糊性Tagsets 标记集Penn Treebank Tags:Derived Tags: 衍生标签Tagged Text Example 标记文本示例Reasons f…

Java 字符串基本操作

一、Java 字符串比较 1、equals用法 String类覆盖了Object类的equals()方法&#xff0c;并提供了自己的实现&#xff0c;它根据它们的内容比较两个字符串的相等性。 equals() 方法用于将字符串与指定的对象比较。 语法 public boolean equals(Object anObject)参数 anObje…

Dockerfile常用指令及其含义

编写dockerfile文件中常用指令&#xff1a; 指令说明FROM指明当前的镜像基于哪个镜像构建:LABEL标记镜像信息&#xff0c;添加元数据ARG定义构建镜像过程中使用的变量ENV指定环境变量VOLUME创建一个数据卷挂载点USER指定运行容器时的用户名或 UIDWORKDIR配置工作目录EXPOSE容器…

chatgpt赋能python:Python区分:为什么选择python?

Python区分&#xff1a;为什么选择python&#xff1f; Python是一种高级语言&#xff0c;一种功能强大且易于学习的编程语言。 它可用于各种领域&#xff0c;包括科学计算&#xff0c;Web开发和数据分析等。 Python的简单性和灵活性使其成为许多行业和开发者的首选编程语言。 …

R语言 tidyverse系列学习笔记(持续更新)

tidyverse 译 “洁净的宇宙” > “极乐净土” 以 iris 鸢尾花数据集为例 ** 查看数据集** ** 查看维度dimention** dim(iris)iris 数据集有150个对象&#xff08;observation&#xff09;&#xff0c;5列 ( Sepal.Length , Sepal.Width , Petal.Length , Petal.Width , Spe…

大疆无人机 MobileSDK(遥控器/手机端)开发 v5版<2>

前言 v5.x版本的功能与v4.x基本相同,都是获取飞机的姿态信息、获取无人机多媒体文件、操作多媒体文件、航线规划等。不过在上一章节中也大致说了一些两个版本的中API的差别,下面是根据一些API使用所完成的一些功能,因为项目原因只能提供部分代码供参考,后续如果有这方面需…

零基础开发小程序第五课-修改数据

目录 1 创建修改页面2 创建远程数据3 给组件绑定默认值4 从详情页跳转到更新页5 刷新页面总结 新手开发往往对修改和删除的功能不是特别理解。我们先按照开发的思路捋一下逻辑&#xff0c;如果想修改数据&#xff0c;首先需要知道修改哪一条数据&#xff0c;然后要把上一次存储…

DINO代码学习笔记(一)

先上官方架构图&#xff1a; 论文地址&#xff1a;https://arxiv.org/pdf/2203.03605.pdf 代码地址&#xff1a;GitHub - IDEA-Research/DINO: [ICLR 2023] Official implementation of the paper "DINO: DETR with Improved DeNoising Anchor Boxes for End-to-End Objec…

什么是数据可视化测试?

在我们日益由数据驱动的世界中&#xff0c;拥有可访问的方式来查看和理解数据比以往任何时候都更加重要。毕竟&#xff0c;员工对数据技能的需求每年都在稳步增长。各级员工和企业主都需要了解数据及其影响。 这就是数据可视化派上用场的地方。为了使数据更易于访问和理解&…

在nodejs addon 环境下抓视频和音频数据包

在node addon 环境下开发音视频&#xff0c;需要用到 gyp 。这个配置比较简单&#xff0c;很快可以配置好。比较坑的是&#xff0c;在vscode 开发环境下&#xff0c; 如果装了conda 或者 mini conda . 有可能会影响gpy程序的编译。谨慎起见&#xff0c;可以看看控制台是否有 …

好物周刊#2:AI 写作助手

不要哀求&#xff0c;学会争取。若是如此&#xff0c;终有所获。 &#x1f388; 项目 vue-fabric-editor 基于 fabric.js 和 Vue 的图片编辑器&#xff0c;可自定义字体、素材、设计模板。 目前已支持以下功能&#xff1a; 导入 JSON 文件保存为 PNG、SVG、JSON 文件插入 S…

我与 INDCODE AI 创作助手的一次对话

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 我与INDCODE AI 创作助手的一次对话 &#x1f9ca;摘要&#x1f9ca;前言&#x1f9ca;对话内容&#x1f9ca;结束语 &#x1f9ca;摘要 本文介绍了 CSDN 嵌入式INSCODE AI 创作助手…

msvcr120.dll丢失怎样修复

MSVCR120.dll是Windows操作系统上一个非常重要的动态链接库文件&#xff0c;它包含了一些运行时库函数&#xff0c;被许多应用程序用来进行编译和运行。如果该文件丢失或损坏&#xff0c;很多应用程序就无法正常运行&#xff0c;这可能会带来一些麻烦。本篇文章将详细介绍MSVCR…

FAT32文件系统详解

FAT32文件系统详细分析 &#xff08;续FAT文件系统详解&#xff09; 文章目录 FAT32文件系统详细分析 &#xff08;续FAT文件系统详解&#xff09;1. 前言2. 格式化SD nand/SD卡3. FAT32文件系统分析3.1 保留区分析3.1.1 BPB(BIOS Parameter Block) 及BS区分析3.1.2 FSInfo 结构…

SpringCloud_微服务基础day1(走进微服务,认识springcloud,微服务(图书管理)项目搭建(一))

官方网站&#xff1a;柏码 - 让每一行代码都闪耀智慧的光芒&#xff01; (itbaima.net) p1:前言&#xff0c;走进微服务 注意&#xff1a;此阶段学习推荐的电脑配置&#xff0c;至少配备4核心CPU&#xff08;主频3.0Ghz以上&#xff09;16GB内存&#xff0c;否则卡到你怀疑人生…

【CH32V】CH32V307驱动4P_OLED

前言 手上正好有 CH32V307 的板子就耍耍&#xff0c;网上4P的OLED例程也不少 4P OLED 屏驱动例程。在加上一些 STM32 标准库的知识&#xff0c;改改引脚定义&#xff0c;就可以将 OLED 屏连接到板子上进行显示了。当然&#xff0c;我也将会分享我整理好的库文件代码和完整的工程…

【22】SCI易中期刊推荐——计算机 | 人工智能(中科院4区)

🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉 | 深度学习Tricks | 第一时间送达<<<📚📚 🚀🚀🚀…

【java 基础二 】- 面向对象、类、接口等

一、定义 Java面向对象编程(OOP)是一种编程范式&#xff0c;其旨在通过将程序逻辑封装在对象中来使代码更易于理解和维护。Java是一种面向对象的编程语言&#xff0c;它支持封装、继承和多态等概念。以下是Java面向对象编程的核心概念&#xff1a; 对象(Object)&#xff1a;对…

BM7 算法

描述 给一个长度为n链表&#xff0c;若其中包含环&#xff0c;请找出该链表的环的入口结点&#xff0c;否则&#xff0c;返回null。 数据范围&#xff1a; n≤10000n≤10000&#xff0c;1<结点值<100001<结点值<10000 要求&#xff1a;空间复杂度 O(1)O(1)&#x…

Linux进程间通信——管道,共享内存,消息队列,信号量

进程间通信 文章目录 进程间通信进程间通信的方式进程间通信的概念如何实现进程间通信管道什么是管道 进程间怎么通信 匿名管道pipe函数创建管道通信读写特征写慢读快写快读慢写端关闭&#xff0c;读端读完读端关闭&#xff0c;写端&#xff1f; 管道特征 命名管道命名管道特性…