C++OpenCV(2):图像处理基础概念与操作

🔆 文章首发于我的个人博客:欢迎大佬们来逛逛
🔆 OpenCV项目地址及源代码:点击这里

文章目录

  • 图形读取与显示
    • 加载图片
    • 显示图片
    • 打印图片信息
    • 保存图片
  • 色彩模型转换
    • RGB颜色模型
    • HSV颜色模型
    • HLS模型
    • LAB模型
  • 图像像素读写操作
  • 像素算数运算
  • 图形文字绘制
    • 绘制线
    • 绘制圆
    • 绘制矩形
    • 绘制椭圆
    • 绘制文字
    • 其他绘制函数

图形读取与显示

通过 imread 我们可以读取一个图片

其形式如下:

void imshow(const String& winname, InputArray mat);

而我们需要传递一个InputArray类型的参数,实际上就是 cv::Mat

如果创建cv::Mat呢?

可以通过它的很多的构造函数

先来了解一下图片的颜色通道

  • 颜色通道
    • RGB 图像有4 个默认通道:红色、绿色和蓝色各有一个通道,以及一个用于编辑图像复合通道(主通道)
  • 彩色深度
    • 8位色,每个像素所能显示的彩色数为2的8次方,即256种颜色。
    • 16位增强色,16位彩色,每个像素所能显示的彩色数为2的16次方,即65536种颜色。
    • 24位真彩色,每个像素所能显示的彩色数为24位,即2的24次方,约1680万种颜色。
    • 32位真彩色,即在24位真彩色图像的基础上再增加一个表示图像透明度信息的Alpha通道。
      • Alpha通道:一张图片的透明和半透明度

我们使用如下的形式来描述它的通道类型:

CV_<bit_depth>(S|U|F)C<number_of_channels>

其中:

  • bit_depth:位数,就是我们上面讲的彩色深度
  • S|U|F:即 signed ,unsigned int,float 来存储
  • number_of_channels:通道,有单通道,双通道,三通道,和四通道等等

加载图片

Mat类型的结构如下:

class  Mat
{
 
public/*
 		flag: 
 		1.数字签名 
 		2.维度
 		3.通道数
 		4.连续性
 	*/
	int flags;					
	int dims; 					//数据维数
	int rows,cols; 				//数据行列
	uchar *data;				//存储的数据		
    const uchar* datastart;		//数据开始
    const uchar* dataend;		//数据结束
    const uchar* datalimit;		//数据边界
	//其他成员  
 	//.....
 	//其他方法
 	//.....
 public: 		//构造方式
    // 默认构造函数 Mat A;
    Mat ()
    // 常用构造函数 Mat A(10,10,CV_8UC3);
    Mat (int rows, int cols, int type)
    //Mat A(300, 400, CV_8UC3,Scalar(255,255,255));
    Mat (int ndims, const int *sizes, int type, const Scalar &s)
    Mat (Size size, int type)
    Mat (int rows, int cols, int type, const Scalar &s)
    Mat (Size size, int type, const Scalar &s)
    Mat (int ndims, const int *sizes, int type)
    Mat (const Mat &m)
    Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
    Mat (Size size, int type, void *data, size_t step=AUTO_STEP)
    Mat (int ndims, const int *sizes, int type, void *data, const size_t *steps=0)
    Mat (const Mat &m, const Range &rowRange, const Range &colRange=Range::all())
    //Mat D (A, Rect(10, 10, 100, 100) );
    Mat (const Mat &m, const Rect &roi)
    Mat (const Mat &m, const Range *ranges)
    
};

我们使用如下的几种方式来加载图片:

  • CV_8UC1:单通道
  • Scalar:使用BGR形式
  • clone/copyTo:从另一个Mat拷贝
void testShow() {
	cv::Mat	m1(200, 200, CV_8UC1);
	cv::imshow("1", m1);
	//std::cout << m << '\n';
	cv::Mat m2(200, 200, CV_8UC3, cv::Scalar(255, 0, 255));
	cv::imshow("2", m2);

	cv::Mat m3 = m2.clone();
	cv::imshow("3", m3);

	cv::Mat m4;
	m3.copyTo(m4);	
	cv::imshow("4", m4);

	//imread
	cv::Mat m5 = cv::imread("images/mm.png", cv::ImreadModes::IMREAD_GRAYSCALE);
	cv::imshow("5", m5);
}

显示图片

我们使用函数:imshow

我们已经直到了它的第二个参数是一个类型,用来表示以何种形式显示图片:**cv::ImreadModes**

Mat imread( const String& filename, int flags = IMREAD_COLOR );
/****************************************************************
*				filename: 文件路径
*				flags   : 显示方式
*****************************************************************/
enum ImreadModes {
       IMREAD_UNCHANGED            = -1,	//按原样返回加载的图像(带有alpha通道,否则会被裁剪)
       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的方向标志旋转图像
};

打印图片信息

我们可以打印Mat的信息,因为它实际上就是一个矩阵,我们可以采用多种形式来格式化输出

  • C语言形式
  • numpy形式
  • python形式

….

void testPrint() {
	cv::Mat m(10, 10, CV_8UC1);
	std::cout << "Mat: \n"<<m << '\n';
	//格式化
	std::cout << "C: \n" << cv::format(m, cv::Formatter::FMT_C);
	std::cout << "numpy: \n" << cv::format(m, cv::Formatter::FMT_NUMPY);
}

保存图片

使用函数: imwrite

第一个参数为保存的图片的路径,第二个参数为保存的图片。

其中路径我们可以使用 cv::String 来传递,就是个字符串。

void testSaveFile(cv::String filename) {
	auto m = cv::imread("./images/dog.png" ,cv::ImreadModes::IMREAD_GRAYSCALE);	
	cv::imshow("dog", m);
	cv::imwrite(filename, m);
}

色彩模型转换

什么是色彩模型?

颜色模型指的是某个三维颜色空间中的一个可见光子集,它包含某个色彩域的所有色彩。一般而言,任何一个色彩域都只是可见光的子集,任何一个颜色模型都无法包含所有的可见光(通俗一点讲就是表示颜色的一种方式

RGB颜色模型

在计算机体系中,最常见的色彩模型就是**RGB颜色**模型。

它具有三维坐标的模型形式:

在这里插入图片描述


  • RGB16:每个像素用16个比特位表示,占2个字节
    • RGB565:RGB分量分别使用5位、6位、5位:

在这里插入图片描述

  • RGB555:RGB分量分别使用5位、5位、5位:

在这里插入图片描述
对于RGB555,如何获取各个5位上的值,即分别获取 R,G,B所代表的值?
通过位运算即可获取。

   /*
   RGB 颜色模型
   */
   struct XColor {
   	unsigned int color : 15;
   };
   void getRGB555() {
   	XColor col{};
   	col.color = 0b110000010111100;
   	std::cout << "R: " << (col.color >> 10) << '\n';
   	std::cout << "G: " << ((col.color & 0x3F0) >> 5) << '\n';
   	std::cout << "B: " << (col.color & 0x1F) << '\n';
   }
  • RGB24格式:每个像素用24比特位表示,占3个字节,在内存中RGB各排列顺序为:BGR:

在这里插入图片描述

  • RGB32格式:每个像素用32比特位表示,占4个字节,R,G,B分量分别用8个bit表示,存储顺序为B,G,R,最后8个字节保留

    • ARGB32:本质就是带alpha通道的RGB24,与RGB32的区别在与,保留的8个bit用来表示透明,也就是alpha的值

    在这里插入图片描述

    • 对于**RGB32**,如何获取各个8位上的值,即分别获取 R,G,B,Alpha所代表的值?

      • 通过位运算即可获取。
      void getRGB32() {
      	int color = 0x0F0A2B0C;
      	std::cout << "B: " << (color >> 24) << '\n';
      	std::cout << "G: " << ((color & 0x00FF0000) >> 16) << '\n';
      	std::cout << "R: " << ((color & 0x0000FF00) >> 8) << '\n';
      	std::cout << "Alpha: " << (color & 0x000000FF) << '\n';
      }
      

HSV颜色模型

HSV(Hue, Saturation,Value)也被称为六角锥体模型,即色调,饱和度,明度

在这里插入图片描述

将RGB转换为HSV模型:

  • **cvtColor**函数:将图像从一种颜色模型转换为另一个。
  • 起到关键作用的是第三个参数:cv::ColorConversionCodes 是一个枚举,表示了你想要从谁转换到谁,这里我们让BGR形式转换为HSV形式。
cv::Mat res;
cv::cvtColor(m1, res, cv::ColorConversionCodes::COLOR_BGR2HSV);
cv::imshow("hsv", res);

在这里插入图片描述

在这里插入图片描述


HLS模型

HLS模型分别是色调,亮度,饱和度

在这里插入图片描述

上图可以看出,固定一个颜色(H),那么随着饱和度(S,Chroma)的增加,颜色越来越深。

cv::cvtColor(m1, res, cv::ColorConversionCodes::COLOR_BGR2HLS);
cv::imshow("hls", res);

在这里插入图片描述

在这里插入图片描述


LAB模型

Lab颜色模型由三个要素组成,一个要素是**亮度**(L),a 和b是两个颜色通道。

  • **a**包括的颜色是从深绿色(低亮度值)到灰色(中亮度值)再到亮粉红色(高亮度值)
  • **b**是从亮蓝色(低亮度值)到灰色(中亮度值)再到黄色(高亮度值)。
  • 因此,这种颜色混合后将产生具有明亮效果的色彩。
    在这里插入图片描述
cv::cvtColor(m1, res, cv::ColorConversionCodes::COLOR_BGR2Lab);
cv::imshow("Lab", res);

在这里插入图片描述

在这里插入图片描述

还有很多的颜色模型都可以在 cvtColor这个函数中找到。


图像像素读写操作

openCV基本类型介绍:

  • 基本类型:
typedef unsigned uint;
typedef signed char schar;
typedef unsigned char uchar;
typedef unsigned short ushort;
  • 封装类型:Vec类似于std::vector,只不过可以指定其大小,并且命名规则为 cv:: Vec大小+ 类型
typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;

typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;

typedef Vec<ushort, 2> Vec2w;
typedef Vec<ushort, 3> Vec3w;
typedef Vec<ushort, 4> Vec4w;

typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<int, 6> Vec6i;
typedef Vec<int, 8> Vec8i;

图像是由像素掉构成的,因此我们可以获取图像的每一个像素,这个像素是由(i,j)确定的,即在图片宽度与高度的范围下,每一个行的每一列都可以是一个像素。

我们使用 Mat 的 at 函数来获取某个位置的像素值。

注意像素具有channels的区别。

  • 如果是单通道: 则直接获取 uchar 表示一个像素(一字节)。
  • 如果是三通道: 则需要获取Vec3b 表示三个像素,可以通过[0],[1],[2]来分别操作。

以下操作对图片转换为负片,使用 255 - 当前像素值

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

class ImgPixel {
public:
	ImgPixel(std::string filename):m(cv::imread(filename)){}
	void show(std::string title) {
		cv::imshow(title, m);
	}
	void Visit_By_Array() {
		auto dims = m.channels(); //获取通道数
		for (int i = 0; i < m.rows; i++) {
			for (int j = 0; j < m.cols; j++) {
				if (dims == 1) {
					//如果是一通道,则直接操作
					uchar rets = m.at<uchar>(i, j);
					rets = 255 - rets;
				}
				if (dims == 3) {
					cv::Vec3b rets = m.at<cv::Vec3b>(i, j);
#if 0
					m.at<cv::Vec3b>(i, j)[0] = 255 - rets[0]; //转换为负片
					m.at<cv::Vec3b>(i, j)[1] = 255 - rets[1];
					m.at<cv::Vec3b>(i, j)[2] = 255 - rets[2];
#else 
					//安全类型转换: 超过255的赋值为 255 小于0的赋值为 0
					m.at<cv::Vec3b>(i, j)[0] = cv::saturate_cast<uchar>(rets[0] + 100);
					m.at<cv::Vec3b>(i, j)[1] = cv::saturate_cast<uchar>(rets[1] + 100);
					m.at<cv::Vec3b>(i, j)[2] = cv::saturate_cast<uchar>(rets[2] + 100);
#endif
				}
			}
		}
	}
private:
	cv::Mat m;
};
int main(){
	ImgPixel img("dog.png");
	img.show("origin");
	img.Visit_By_Array();
	img.show("convert1");

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

安全类型转换:saturate_cast<T> 是openCV的一种安全转换函数,当我们对像素执行加减乘除的时候,有可能会超出 [ 0 , 255 ] [0,255] [0,255]
的范围,因此使用此函数来保证不会越界。

实际上这个函数就是:

  • 超过255:转为255
  • 小于0:转为0
template<> inline uchar saturate_cast<uchar>(int v)          { return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); }

像素算数运算

图像可以进行像素之间的算数运算,跟我们上节的对像素的简单减法是一样的:

我们有专门的函数:

  • add:像素加
  • subtract:像素减
  • multiply:像素乘
  • divide:像素除
  • addWeighted:对图片执行: α ⋅ i m g 1 + β ⋅ i m g 2 = r e s \alpha\cdot img_1 + \beta\cdot img_2 = res αimg1+βimg2=res 的操作,其中的 α \alpha α β \beta β就是透明度

除了基本的运算,还有二进制运算

  • and:像素按位与
  • or:按位或
  • **not:**按位取反
  • xor:按位异或

测试如下:

需要两个原图片执行下面的这些操作,我使用的图片是:(注意尺寸要一样)

在这里插入图片描述

然后自行执行下面代码。

在这里插入图片描述

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

class ImgOperation {
public:
	ImgOperation() :m1(cv::imread("dog.png")), m2(cv::imread("text.jpg")) {}
	void testAdd(std::string title="add") {
		cv::add(m1, m2, res);
		cv::imshow(title, res);
		cv::waitKey();
	}
	void testSub(std::string title = "subtract") {
		cv::subtract(m1, m2, res);
		cv::imshow(title, res);
		cv::waitKey();
	}
	void testMul(std::string title = "multiply") {
		cv::multiply(m1, m2, res);
		cv::imshow(title, res);
		cv::waitKey();
	}
	void testDivide(std::string title = "divide") {
		cv::divide(m1, m2, res);
		cv::imshow(title, res);
		cv::waitKey();
	}
	void testAddWeighted(std::string title="AddWeighted") {
		cv::addWeighted(m1, 0.1, m2, 0.9, 0, res);
		cv::imshow(title, res);
		cv::waitKey();
	}
	//BitWise
	void testBitWise() {
		cv::Mat _and, _or, _xor, _not;
		cv::bitwise_and(m1, m2, _and);
		cv::bitwise_or(m1, m2, _or);
		cv::bitwise_xor(m1, m2, _xor);
		cv::bitwise_not(m1, _not);

		cv::imshow("and", _and);
		cv::imshow("or", _or);
		cv::imshow("xor", _xor);
		cv::imshow("not", _not);
	}
private:
	cv::Mat m1;
	cv::Mat m2;
	cv::Mat res;
};

int main()
{
	ImgOperation opt;
	//opt.testAdd();
	//opt.testSub();
	//opt.testMul();
	//opt.testDivide();
	//opt.testAddWeighted();	
	opt.testBitWise();

	cv::waitKey();
	return 0;
}

图形文字绘制

绘制线

使用**line**函数,原型如下:

void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,int thickness = 1, int lineType = LINE_8, int shift = 0);
//线的样式
enum LineTypes {
    FILLED  = -1,
    LINE_4  = 4, //!< 4-connected line
    LINE_8  = 8, //!< 8-connected line
    LINE_AA = 16 //!< antialiased line
};
/*******************************************************************
*			img: 			绘制在那个图像上
*			pt1:			起点
*			pt2:			终点
*			color:			颜色
*			thickness:		厚度(宽度) 
*			lineType:		线的样式
*					FILLED: 线填充的
*					LINE_4:	4邻接连接线
*					LINE_8: 8邻接连接线
*					LINE_AA:反锯齿连接线(高斯滤波)
*			shift: 			坐标点小数点位数(可忽略不写)
*********************************************************************/

在执行 imshow的之前,在图片上画一条线:

void testDrawLine() {
		//绘制线
		cv::line(m, cv::Point(0, 0), cv::Point(300, 300), cv::Scalar(0,255,0), 3, cv::LineTypes::LINE_AA);
	}

在这里插入图片描述


绘制圆

使用**circle函数来绘制或者填充圆**

void circle(InputOutputArray img, Point center, int radius,const Scalar& color, int thickness = 1,int lineType = LINE_8, int shift = 0);
//线的样式
enum LineTypes {
    FILLED  = -1,
    LINE_4  = 4, //!< 4-connected line
    LINE_8  = 8, //!< 8-connected line
    LINE_AA = 16 //!< antialiased line
};
/*******************************************************************
*			img: 			绘制在那个图像上
*			center:			圆心坐标
*			radius:			半径
*			color:			颜色
*			thickness:		厚度(宽度)
*								-1: 	填充圆
*								其他值:  空心
*			lineType:		 线的样式
*					FILLED: 线填充的
*					LINE_4:	4邻接连接线
*					LINE_8: 8邻接连接线
*					LINE_AA:反锯齿连接线(高斯滤波)
*			shift: 			坐标点小数点位数(可忽略不写)
*********************************************************************/

效果如下:

  • 填充效果需要把thickness置为-1。
void testDrawCircle() {
		cv::circle(m, cv::Point(150, 150), 50, cv::Scalar(0, 255, 0),-1); //填充圆
		cv::circle(m, cv::Point(150, 150), 52, cv::Scalar(0, 0, 255), 2, 
							cv::LineTypes::LINE_AA); //空心圆
	}

在这里插入图片描述


绘制矩形

使用rectangle函数来绘制矩形。

void rectangle(InputOutputArray img, Rect rec,const Scalar& color, int thickness = 1,int lineType = LINE_8, int shift = 0);
/*******************************************************************
*			img: 			绘制在那个图像上
*			rec:			矩形大小  Rect(x,y,w,h);  
*					x,y:	起始坐标
*					w,h:	宽度和高度
*			color:			颜色
*			thickness:		厚度(宽度)
*								-1: 	填充矩形
*								其他值:  空心矩形
*			lineType:		线的样式
*					FILLED: 线填充的
*					LINE_4:	4邻接连接线
*					LINE_8: 8邻接连接线
*					LINE_AA:反锯齿连接线(高斯滤波)
*			shift: 			坐标点小数点位数(可忽略不写)
*********************************************************************/

效果如下:

void testDrawRectangle() {
		cv::rectangle(m, cv::Rect(0, 0, 50, 50), cv::Scalar(100, 45, 20),-1);
	}

在这里插入图片描述


绘制椭圆

使用ellipse来绘制椭圆:

void ellipse(InputOutputArray img, Point center, Size axes,double angle, double startAngle, double endAngle,
const Scalar& color, int thickness = 1,int lineType = LINE_8, int shift = 0);
/*******************************************************************
*			img: 			绘制在那个图像上
*			center:			椭圆圆心
*			axes:			矩形内置椭圆
*			angle:			倾斜角
*			startAngle:		扩展的弧度 0
*			endAngle:		 扩展的弧度  360
*			color:			颜色
*			thickness:		线宽度
*								-1: 	填充矩形
*								其他值:  空心矩形
*			lineType:		线的样式
*					FILLED: 线填充的
*					LINE_4:	4邻接连接线
*					LINE_8: 8邻接连接线
*					LINE_AA:反锯齿连接线(高斯滤波)
*			shift: 			坐标点小数点位数(可忽略不写)
*********************************************************************/

效果如下:

void testDrawEllipse() {
		cv::ellipse(m, cv::Point(100, 100),cv::Size(20,80),
						180,0,360, cv::Scalar(54, 54, 43));
		cv::ellipse(m, cv::Point(100, 100), cv::Size(20, 80), 
						90, 0, 360, cv::Scalar(54, 54, 43),-1);
	}

在这里插入图片描述


绘制文字

使用**putText来绘制文字,注意不支持中文!!!!!!!!!!!!!**

void putText( InputOutputArray img, const String& text, Point org,int fontFace, double fontScale, Scalar color,int thickness = 1, int lineType = LINE_8,bool bottomLeftOrigin = false );
/*******************************************************************
*			img: 			绘制在那个图像上
*			text:			绘制文字
*			org:			文本框左下角
*			fontFace:		字体
*			fontScale:		缩放
*			color:			颜色
*			thickness		线宽度
*			lineType:		线的样式
*					FILLED: 线填充的
*					LINE_4:	4邻接连接线
*					LINE_8: 8邻接连接线
*					LINE_AA:反锯齿连接线(高斯滤波)
*			bottomLeftOrigin: 		起点位置
*								true:  左上角  反转倒立显示
*								false: 左下角  正常显示
*********************************************************************/
//opencv 不识别汉字
//fontFace: 字体
enum HersheyFonts {
    FONT_HERSHEY_SIMPLEX        = 0, //!< normal size sans-serif font   //灯芯体
    FONT_HERSHEY_PLAIN          = 1, //!< small size sans-serif font
    FONT_HERSHEY_DUPLEX         = 2, //!< normal size sans-serif font (more complex than FONT_HERSHEY_SIMPLEX)
    FONT_HERSHEY_COMPLEX        = 3, //!< normal size serif font
    FONT_HERSHEY_TRIPLEX        = 4, //!< normal size serif font (more complex than FONT_HERSHEY_COMPLEX)
    FONT_HERSHEY_COMPLEX_SMALL  = 5, //!< smaller version of FONT_HERSHEY_COMPLEX
    FONT_HERSHEY_SCRIPT_SIMPLEX = 6, //!< hand-writing style font
    FONT_HERSHEY_SCRIPT_COMPLEX = 7, //!< more complex variant of FONT_HERSHEY_SCRIPT_SIMPLEX
    FONT_ITALIC                 = 16 //!< flag for italic font
};

测试如下:

void testDrawText(const std::string& name) {
		cv::putText(m,
			name,
			cv::Point(10, 200),
			cv::HersheyFonts::FONT_HERSHEY_COMPLEX,
			1.0,
			cv::Scalar(50,50,255),
			2,
			cv::LineTypes::LINE_AA,
			false); //翻转
	}

在这里插入图片描述


其他绘制函数

绘制多边形线:

  • polylines

绘制填充多边形:

  • fillPoly

文本参考

百度百科_全球领先的中文百科全书

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL数据库第十一课---------SQl语句的拔高-------水平提升

作者前言 个人主页::小小页面 gitee页面:秦大大 一个爱分享的小博主 欢迎小可爱们前来借鉴 ______________________________________________________ 目录 SQL提高 日期函数 length round reverse substring ifnull case when cast grouping sets 排序函数 开窗函…

计算机视觉(二)图像特征提取

文章目录 颜色特征量化颜色直方图适用颜色空间&#xff1a;RGB、HSV等颜色空间操作 几何特征边缘 Edge边缘定义边缘提取 基于关键点的特征描述子引入几何特征&#xff1a;关键点几何特征&#xff1a;Harris角点FAST角点检测几何特征&#xff1a;斑点局部特征&#xff1a;SIFT预…

【Linux从入门到精通】进程的控制(进程替换)

本篇文章会对进程替换进行讲解。希望本篇文章会对你有所帮助 文章目录 一、进程替换概念 二、进程替换函数 2、1 execl 2、2 execlp 2、3 execv 2、3 execle 2、4 execve 三、总结 &#x1f64b;‍♂️ 作者&#xff1a;Ggggggtm &#x1f64b;‍♂️ &#x1f440; 专栏&…

视频讲解Codeforces Round 887 (Div. 2)(A--C)

文章目录 A. Desorting1、板书2、代码 B. Fibonaccharsis1、板书2、代码 C. Ntarsis Set1、板书2、代码 视频讲解Codeforces Round 887 (Div. 2)&#xff08;A–C&#xff09; A. Desorting 1、板书 2、代码 #include<bits/stdc.h> #define endl \n #define INF 0x3f…

区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型

区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型 目录 区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于QRF随机森林分位数回归时间序列区间预测模型&#xff1…

从零到一nvm、npm、cnpm、yarn、vue全套安装和环境配置以及创建新项目和如何运行人家的项目大全,最详细,保姆级

NVM 1.下载 下载地址&#xff1a;Releases coreybutler/nvm-windows GitHub 可能需要开启魔法 划到下面。找到如图所示的文件下载即可2. 2.安装&#xff08;要记住安装的路径&#xff09; 基本一键默认即可&#xff0c;你要修改路径也可以&#xff0c;但不建议 下载好…

【开发问题】flink-cdc不用数据库之间的,不同类型的转化

不同的数据库之期间数据类型转化 问题来源与原因解决过程&#xff0c;思路错误&#xff0c;导致各种错误错误思路是什么 正确解决方式&#xff0c;找官网对应的链接器&#xff0c;数据转化 问题来源与原因 我一开始是flink-cdc&#xff0c;oracle2Mysql&#xff0c;sql 我一开…

删除Windows顽固启动项Program

卸载软件之后可能会遇到任务管理器中启动项显示有Program这种无效项目的情况 无效项目如图所示: 解决方法 打开注册表 Win R 打开注册表后定位到 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run 可以直接复制粘贴到地址栏进行跳…

Orangepi docker Home Assistant部署

手册上多数应用在树莓派用过&#xff0c;发现一个Home Assistant之前没搞过 按照手册先安装docker&#xff0c;使用enable_docker.sh 然后使用 docker run hello-world 来测试docker是否成功&#xff0c;如果hello from docker&#xff0c;即正常 通过以下docker命令搜索hom…

微服务探索之路06篇k8s配置文件Yaml部署Redis使用Helm部署MongoDB和kafka

1 安装Redis 1.1创建配置文件redis.conf 切换到自己的目录下如本文是放在/home/ubuntu下 cd /home/ubuntuvim redis.conf bind 0.0.0.0 protected-mode yes port 6379 requirepass qwe123456 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no pidfile /var/run/r…

【Spring】ApplicationEventPublisher 发布订阅模式

概念 关于发布订阅这个词&#xff0c;其实不仅仅出现在Spring框架当中&#xff0c;其实在Redis中也有存在&#xff08;其对应的是convertAndSend()方法&#xff09;&#xff0c;还有在MQ消息队列里也是有的&#xff0c;但这里就主要介绍的是关于Spring框架的ApplicationEventPu…

怎么把PDF转为word?1分钟解决难题

PDF文件在我们的电脑上应用非常广泛&#xff0c;由于其较高的安全性和兼容性&#xff0c;得到了广泛的认可。然而&#xff0c;对于一些人来说&#xff0c;PDF文件不能直接进行编辑和修改可能是一个问题。因此&#xff0c;通常我们需要将其转换为Word格式&#xff0c;以便在Word…

成为“AI+的UGC社交平台”,亚马逊云科技助力博宇盖乐向“3D UGC社交门户”迈进

随着元宇宙浪潮逐渐升温&#xff0c;以玩家为主导的UGC游戏平台获得空前关注。多元化的视觉呈现方式&#xff0c;人人可参与、交互的玩法生态&#xff0c;具有UGC属性的游戏平台在极大提升玩家参与度、增加游戏趣味性的同时&#xff0c;也为游戏行业的内容创作带来了新的想象空…

5分钟开发一个AI论文抓取和ChatGPT提炼应用

5分钟开发一个AI论文抓取和ChatGPT提炼应用 第一步 点击“即刻开始” -选择模板 python -修改标题 “AIPaper”&#xff0c;项目标识“AIPaper”&#xff0c;点击“创建项目” 第二步 在编程区域右侧AI区域&#xff0c;输入框输入以下内容&#xff1a; 请根据下面的内容&…

MacBook外接键盘修改键位

众所周知&#xff0c;MacBook的键盘和Windows差别很大&#xff0c;比如我们最常用的ctrlcv在Mac下是commandcv…而外接键盘往往是Windows布局&#xff0c;因此如何修改外接键盘键位就是一件很重要的事情&#xff01; 首先&#xff0c;我们要知道Win键在Mac系统中是多余的&…

客户案例 | 思腾合力服务器助力西安电子科技大学人工智能实验室建设

客户介绍 西安电子科技大学是以信息与电子学科为主&#xff0c;工、理、管、文多学科协调发展的全国重点大学&#xff0c;直属教育部&#xff0c;是国家“优势学科创新平台”项目和“211工程”项目重点建设高校之一、国家双创示范基地之一、首批35所示范性软件学院、首批9所示范…

机器学习术语解析与应用(一)

文章目录 &#x1f340;引言&#x1f340;数据集&#x1f340;特征工程&#xff08;Feature Engineering&#xff09;&#x1f340;模型&#xff08;Model&#xff09;&#x1f340;算法&#xff08;Algorithm&#xff09;&#x1f340;训练&#xff08;Training&#xff09;&a…

电脑风扇声音大怎么办?最全解决方法分享!

家人们谁懂啊&#xff01;电脑风扇声音太大了&#xff0c;每天用电脑的时候都感觉特别特别的吵&#xff0c;真的非常窒息&#xff0c;有什么方法可以改善电脑风扇声太吵的情况吗&#xff1f; 电脑风扇是保持电脑内部温度稳定的重要组件&#xff0c;其正常运行有利于保障我们电脑…

学好Elasticsearch系列-核心概念

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 文章目录 节点角色master&#xff1a;候选节点data&#xff1a;数据节点Ingest&#xff1a;预处理节点ml&#xff1a;机器学习节点remote_ cluster_ client&#xff1a;候选客户端节点transform&#xff1a;…

Flutter实现点击头像更新头像的功能,本地相册选取和调用相机两种方式的实现

文章目录 需求实现的效果如图代码实现代码分析用InkWell包住了我们的头像&#xff0c;这样来监听点击头像的事件用showDialog弹出提示框让用户选择是从相册里选择头像还是使用相机来拍照用image_picker实现从设备的相册或相机中选择图片或拍照 需求 Flutter实现点击头像更新头…