【OpenCV(C++)快速入门】--opencv学习

0 配置环境

配置环境网上很多资料,这里就不赘述了。

笔者使用的是VS2022+opencv4.9.0

测试配置环境

// 打开摄像头样例
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/core/core.hpp>  
using namespace cv;int main()
{VideoCapture cap(0);Mat frame;while (1){cap >> frame;imshow("调用摄像头", frame);waitKey(30);}return 0;
}

如果配置正确,会调用电脑摄像头

1 读图片和视频

读图片

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <string>images ///
int main()
{std::string path = "Resources/test.png";		// 图片路径cv::Mat img = cv::imread(path);					// 读数据cv::imshow("Image", img);						// 显示数据cv::waitKey(0);									// 增加延时,0表示无穷return 0;
}

读视频

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <string>video ///
// 视频是一系列的图像,因此需要遍历所有的图像/帧,捕获并且显示
int main()
{std::string path = "Resources/test_video.mp4";	// 视频路径cv::VideoCapture capture(path);cv::Mat img;while (1){capture.read(img);							// 读到img中cv::imshow("Vedio", img);					// 显示cv::waitKey(20);							// 延时20ms,数值越大,视频越慢}return 0;
}

读相机

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <string>Webcam ///
// 视频是一系列的图像,因此需要遍历所有的图像/帧,捕获并且显示
int main()
{cv::VideoCapture capture(0);					// 只有一个相机cv::Mat img;while (1){capture.read(img);							// 读到img中cv::imshow("Vedio", img);					// 显示cv::waitKey(1);								// 延时1ms,数值越大,视频越慢}return 0;
}

2 基本函数

cvtColor

// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间
// 把img转换成imgGray
cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);
  • img:输入图像,这是一个BGR格式的彩色图像。

  • imgGray:输出图像,转换后的灰度图像。

  • cv::COLOR_BGR2GRAY:转换代码,表示将BGR格式的图像转换为灰度图像。

GaussianBlur

高斯模糊处理

// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊
// 把img模糊成imgBlur
cv::GaussianBlur(img, imgBlur, cv::Size(7, 7), 5, 0);
  • cv::GaussianBlur是OpenCV中的一个函数,用于对图像进行高斯模糊处理。高斯模糊是一种图像处理技术,通过使用高斯核对图像进行卷积,可以有效地减少图像的噪声和细节,使图像变得模糊。

  • 参数解释

    • img:输入图像,这是一个cv::Mat类型的对象,表示要进行高斯模糊处理的图像。

    • imgBlur:输出图像,经过高斯模糊处理后的图像,也是一个cv::Mat类型的对象。

    • cv::Size(7, 7):高斯核的大小,表示高斯核的宽度和高度。这里使用7×7的高斯核。高斯核的大小必须是正奇数,以确保核的中心能够对准图像的每个像素。

    • 5:高斯核的标准差(σ)在X方向上的值。标准差越大,模糊效果越明显。如果设置为0,OpenCV会根据高斯核的大小自动计算标准差。

    • 0:高斯核的标准差(σ)在Y方向上的值。如果设置为0,OpenCV会使用与X方向相同的标准差。

Canny

边缘检测

// 边缘检测,阈值1,2可调,目的:显示更多的边缘,使用模糊的图像
cv::Canny(imgBlur, imgCanny, 25, 75);
  • cv::Canny是OpenCV中的一个函数,用于执行Canny边缘检测算法。Canny边缘检测是一种多步骤的算法,包括高斯模糊、梯度计算、非极大值抑制和双阈值检测等步骤。

  • 参数解释

    • imgBlur:输入图像,这是一个经过高斯模糊处理的cv::Mat类型的对象。高斯模糊处理可以减少图像的噪声,使边缘检测更加准确。

    • imgCanny:输出图像,经过Canny边缘检测后的图像,也是一个cv::Mat类型的对象。输出图像是一个二值图像,边缘部分的像素值为255,非边缘部分的像素值为0。

    • 25:低阈值(threshold1),用于Canny边缘检测中的双阈值检测。低阈值用于确定弱边缘。

    • 75:高阈值(threshold2),用于Canny边缘检测中的双阈值检测。高阈值用于确定强边缘。

dilate和erode

膨胀和侵蚀

// 扩大和侵蚀图像
// 创建一个核,增加Size(只能是奇数)会扩张/侵蚀更多
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
cv::dilate(imgCanny, imgDila, kernel);			// 扩张边缘,增加边缘厚度
cv::erode(imgDila, imgErode, kernel);			// 侵蚀边缘,减小边缘厚度
  • cv::getStructuringElement

    • cv::getStructuringElement是OpenCV中的一个函数,用于创建形态学操作的结构元素(也称为核或掩模)。

  • 参数解释

    • cv::MORPH_RECT:指定结构元素的形状为矩形。

    • cv::Size(3, 3):指定结构元素的大小为3×3。这意味着结构元素是一个3×3的矩形,中心像素为(1, 1)。

  • cv::dilate

    • cv::dilate是OpenCV中的一个函数,用于对图像进行膨胀操作。膨胀操作可以扩大图像中的白色区域,通常用于连接断开的部分或填补小孔。

  • 参数解释

    • imgCanny:输入图像,这是一个经过Canny边缘检测的二值图像。

    • imgDila:输出图像,经过膨胀操作后的图像。

    • kernel:结构元素,用于定义膨胀操作的邻域。

  • cv::erode

    • cv::erode是OpenCV中的一个函数,用于对图像进行腐蚀操作。腐蚀操作可以缩小图像中的白色区域,通常用于去除小的噪点或分离粘连的部分。

  • 参数解释

    • imgDila:输入图像,这是一个经过膨胀操作的图像。

    • imgErode:输出图像,经过腐蚀操作后的图像。

    • kernel:结构元素,用于定义腐蚀操作的邻域。

总体代码

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>basic functions ///
int main()
{std::string path = "Resources/test.png";		// 图片路径cv::Mat img = cv::imread(path);					// 读数据cv::Mat imgGray, imgBlur, imgCanny, imgDila, imgErode;// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间// 把img转换成imgGraycv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊// 把img模糊成imgBlurcv::GaussianBlur(img, imgBlur, cv::Size(7, 7), 5, 0);// 边缘检测,阈值1,2可调,目的:显示更多的边缘,使用模糊的图像cv::Canny(imgBlur, imgCanny, 25, 75);// 扩大和侵蚀图像// 创建一个核,增加Size(只能是奇数)会扩张/侵蚀更多cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));cv::dilate(imgCanny, imgDila, kernel);			// 扩张边缘,增加边缘厚度cv::erode(imgDila, imgErode, kernel);			// 侵蚀边缘,减小边缘厚度cv::imshow("Image", img);						// 显示数据cv::imshow("Image Gray", imgGray);				// 显示灰色数据cv::imshow("Image Blur", imgBlur);				// 显示模糊数据cv::imshow("Image Canny", imgCanny);			// 显示边缘检测数据cv::imshow("Image imgDila", imgDila);			// 显示扩张边缘数据cv::imshow("Image imgErode", imgErode);			// 显示侵蚀检测数据cv::waitKey(0);									// 增加延时,0表示无穷return 0;
}

测试

3 resize and crop

调整图片和裁剪图片

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>using namespace std;
using namespace cv;resize and crop ///int main(int argc, char** argv)
{string path = "Resources/test.png";		// 图片路径cv::Mat img = cv::imread(path);			// 读图片cv::Mat imgResize, imgCrop;				// 调整图片和裁剪图片// [768 x 559]//std::cout << img.size() << std::endl;// 调整大小//cv::resize(img, imgResize, Size(), 0.5, 0.5);  // 长宽各自缩小0.5cv::resize(img, imgResize, Size(680, 400));		 // 缩小到680*400// 裁剪// 从200*100处开始裁剪,各自裁剪300cv::Rect rect(200, 100, 300, 300);imgCrop = img(rect);// 显示cv::imshow("Image", img);cv::imshow("Image Resize", imgResize);cv::imshow("Image Crop", imgCrop);cv::waitKey(0);									// 增加延时,0表示无穷return 0;
}

测试

4 Draw shapes and Text

#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>using namespace std;
using namespace cv;Draw shapes and Text ///int main(int argc, char** argv)
{// blank image// 8bit3通道,白色cv::Mat img(512, 512, CV_8UC3, cv::Scalar(255, 255, 255));// 基于上图画一个圆,圆心在(256,256)处,半径是155,颜色是0, 69, 255,厚度是10// cv::circle(img, cv::Point(256, 256), 155, cv::Scalar(0, 69, 255), 10);cv::circle(img, cv::Point(256, 256), 155, cv::Scalar(0, 69, 255), FILLED);	// 填充// 画一个矩形// 左上角是(130, 226),右下角是(382, 286)// 颜色是cv::Scalar(255, 255, 255),厚度是3//cv::rectangle(img, cv::Point(130, 226), cv::Point(382, 286), cv::Scalar(255, 255, 255), 3);cv::rectangle(img, cv::Point(130, 226), cv::Point(382, 286), cv::Scalar(255, 255, 255), FILLED);// 画一条线cv::line(img, Point(130, 296), cv::Point(382, 296), cv::Scalar(255, 255, 255), 2);//cv::line(img, Point(130, 296), cv::Point(382, 450), cv::Scalar(255, 255, 255), 2);// 本文// FONT_HERSHEY_DUPLEX字体,0.75是比例cv:putText(img, "StudyWinter", cv::Point(160, 262), cv::FONT_HERSHEY_DUPLEX, 0.75, cv::Scalar(0, 69, 255));cv::imshow("Image", img);cv::waitKey(0);return 0;
}

测试

5 wrap images

图像扭曲

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>using namespace std;
using namespace cv;wrap images ///
float w = 250, h = 350;
cv::Mat matrix, imgWrap;int main(int argc, char** argv)
{string path = "Resources/cards.jpg";			// 图片路径cv::Mat img = cv::imread(path);					// 读数据cv::Point2f src[4] = { {529, 142}, {771, 190}, {405, 395}, {674, 457} };cv::Point2f dst[4] = { {0.0f, 0.0f}, {w, 0.0f}, {0.0f, h}, {w, h} };使用圆圈,取四个点在图中标记,放在这里转换后图片有圆//for (int i = 0; i < 4; i++)//{//	cv::circle(img, src[i], 10, cv::Scalar(0, 0, 255), FILLED);//}// 转换matrix = getPerspectiveTransform(src, dst);cv::warpPerspective(img, imgWrap, matrix, cv::Point(w, h));// 使用圆圈,取四个点在图中标记for (int i = 0; i < 4; i++){cv::circle(img, src[i], 10, cv::Scalar(0, 0, 255), FILLED);}cv::imshow("Image", img);						// 显示数据cv::imshow("Image Warp", imgWrap);				// 显示数据cv::waitKey(0);return 0;
}

这段代码的主要功能是读取一张图像,定义四个源点和对应的目标点,计算透视变换矩阵,对图像进行透视变换,并在源图像中标记源点,最后显示原始图像和变换后的图像。通过这种方式,可以将图像中的某个区域(如一张卡片)从任意角度变换为正视图。

测试

6 Color detection

test1

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <string>Color detection ///
cv::Mat imgHSV, mask;
// h色调 s饱和度 v明度
int hmin = 0, smin = 110, vmin = 153;
int hmax = 19, smax = 240, vmax = 255;int main()
{std::string path = "Resources/lambo.png";		// 图片路径cv::Mat img = cv::imread(path);					// 读数据// 颜色转换cv::cvtColor(img, imgHSV, cv::COLOR_BGR2HSV);// 创建窗口cv::namedWindow("Trackbars");// 创建跟踪栏cv::createTrackbar("Hue Min", "Trackbars", &hmin, 179);cv::createTrackbar("Hue Max", "Trackbars", &hmax, 179);cv::createTrackbar("Sat Min", "Trackbars", &smin, 255);cv::createTrackbar("Sat Max", "Trackbars", &smax, 255);cv::createTrackbar("Val Min", "Trackbars", &vmin, 255);cv::createTrackbar("Val Max", "Trackbars", &vmax, 255);while (1){// 定义标量cv::Scalar lower(hmin, smin, vmin);cv::Scalar upper(hmax, smax, vmax);cv::inRange(imgHSV, lower, upper, mask);cv::imshow("Image", img);						// 显示数据cv::imshow("image HSV", imgHSV);				// 显示数据cv::imshow("image Mask", mask);					// 显示数据cv::waitKey(0);									// 增加延时,0表示无穷}return 0;
}

这段代码的主要功能是读取一张图像,将其从BGR颜色空间转换为HSV颜色空间,通过创建跟踪栏动态调整HSV颜色空间中的阈值,生成掩码图像,并显示原始图像、HSV图像和掩码图像。通过调整跟踪栏,可以实时看到不同阈值下检测到的颜色区域。

7 形状轮廓检测

这小节,将会通过OpenCV提供的函数进行,简单的形状检测,并给检测出来的形状添加boundingbox。整个过程的流程如下图所示:

图像的预处理阶段,实质上就是通过灰度处理、高斯模糊、边缘检测然后再加粗边缘得到一个二值化的图像,便于边界检测函数进行检测。

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>///int main(int argc, char** argv)
{std::string path = "Resources/shapes.png";		// 图片路径cv::Mat img = cv::imread(path);					// 读数据// 预处理// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间。cv::Mat imgGray, imgBlur, imgCanny, imgDil;cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊cv::GaussianBlur(imgGray, imgBlur, cv::Size(3, 3), 3, 0);// 边缘检测,阈值1,2可调,目的:显示更多的边缘cv::Canny(imgBlur, imgCanny, 25, 75);// 创建一个核,增加Size(只能是奇数),会扩张/侵蚀更多cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));cv::dilate(imgCanny, imgDil, kernel);cv::imshow("Image", img);cv::imshow("Image Gray", imgGray);cv::imshow("Image Blur", imgBlur);cv::imshow("Image Canny", imgCanny);cv::imshow("Image dilate", imgDil);cv::waitKey(0);return 0;
}

测试

图片预处理之后,便可以进行形状检测了,需要使用到以下的函数:

void findContours(InputArray image, OutputArrayOfArrays contours,OutputArray hierarchy, int mode,int method);

InputArray image :这需要我们预处理之后得到的二值化图像(8bit单通道图像);

OutputArrayOfArrays contours:这是函数的输出,它是std::vector<vector> 类型的,可以看成是一个存储多个向量的组。每一个向量代表一个形状。

OutputArray hierarchy:该变量存储了contours中对应元素的相关拓扑信息,其类型为std::vector< cv::Vec4i > 。Vec4i 即 std::vector<int, 4>类型。

int mode,int method :这里的mode 和 method是指形状检测的模式和方法,OpenCV提供了多种的模式和方法,这里不细讲,详细的可以去官网查一下。

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>///// imgDil是传入的扩张边缘的图像用来查找轮廓,img是要在其上绘制轮廓的图像
void getContours(cv::Mat imgDil, cv::Mat img)
{// 轮廓检测到的轮廓。每个轮廓线存储为一个点的向量std::vector<std::vector<cv::Point>> contours;// 包含关于映像拓扑的信息  typedef Vec<int, 4> Vec4i;具有4个整数值std::vector<cv::Vec4i> hierarchy;// 在二值图像中查找轮廓cv::findContours(imgDil, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);// 获得提取的轮廓以后,通过下面的函数将检测到的轮廓在图上表示出来// 其中 -1 表示把全部检测到的轮廓都输出, 向量Scalar(255, 0, 255) 表示颜色, 2 表示轮廓厚度cv::drawContours(img, contours, -1, cv::Scalar(255, 0, 255), 2);}int main(int argc, char** argv)
{std::string path = "Resources/shapes.png";		// 图片路径cv::Mat img = cv::imread(path);					// 读数据// 预处理// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间。cv::Mat imgGray, imgBlur, imgCanny, imgDil;cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊cv::GaussianBlur(imgGray, imgBlur, cv::Size(3, 3), 3, 0);// 边缘检测,阈值1,2可调,目的:显示更多的边缘cv::Canny(imgBlur, imgCanny, 25, 75);// 创建一个核,增加Size(只能是奇数),会扩张/侵蚀更多cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));cv::dilate(imgCanny, imgDil, kernel);// 形状检测getContours(imgDil, img);cv::imshow("Image", img);//cv::imshow("Image Gray", imgGray);//cv::imshow("Image Blur", imgBlur);//cv::imshow("Image Canny", imgCanny);//cv::imshow("Image dilate", imgDil);cv::waitKey(0);return 0;
}

测试

不难发现,图像中的所有形状都被检测出来了,因为这张图像是比较理想情况,如果图像中出现一些噪点(例如图像中右上角的小黑圆圈),很可能也会被检测出来,这是不想看到的,这个时候,需要采取一些手段来去除这些噪点,这里提供一种根据形状图像面积过滤小形状的方法:

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>///// imgDil是传入的扩张边缘的图像用来查找轮廓,img是要在其上绘制轮廓的图像
void getContours(cv::Mat imgDil, cv::Mat img)
{// 轮廓检测到的轮廓。每个轮廓线存储为一个点的向量std::vector<std::vector<cv::Point>> contours;// 包含关于映像拓扑的信息  typedef Vec<int, 4> Vec4i;具有4个整数值std::vector<cv::Vec4i> hierarchy;// 在二值图像中查找轮廓cv::findContours(imgDil, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);// 获得提取的轮廓以后,通过下面的函数将检测到的轮廓在图上表示出来// 其中 -1 表示把全部检测到的轮廓都输出, 向量Scalar(255, 0, 255) 表示颜色, 2 表示轮廓厚度//cv::drawContours(img, contours, -1, cv::Scalar(255, 0, 255), 2);// 根据形状图像面积过滤小形状for (int i = 0; i < contours.size(); i++){// 获取每个形状的面积double area = cv::contourArea(contours[i]);if (area - 15000 > 0.00000001 || area - 15000 > -0.00000001){// 输出cv::drawContours(img, contours, i, cv::Scalar(255, 0, 255), 2);}}}int main(int argc, char** argv)
{std::string path = "Resources/shapes.png";		// 图片路径cv::Mat img = cv::imread(path);					// 读数据// 预处理// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间。cv::Mat imgGray, imgBlur, imgCanny, imgDil;cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊cv::GaussianBlur(imgGray, imgBlur, cv::Size(3, 3), 3, 0);// 边缘检测,阈值1,2可调,目的:显示更多的边缘cv::Canny(imgBlur, imgCanny, 25, 75);// 创建一个核,增加Size(只能是奇数),会扩张/侵蚀更多cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));cv::dilate(imgCanny, imgDil, kernel);// 形状检测getContours(imgDil, img);cv::imshow("Image", img);//cv::imshow("Image Gray", imgGray);//cv::imshow("Image Blur", imgBlur);//cv::imshow("Image Canny", imgCanny);//cv::imshow("Image dilate", imgDil);cv::waitKey(0);return 0;
}

测试

添加此函数以后,可以看到,面积小于15000的没有被表示出来。

8 检测人脸

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <iostream>Webcam ///
// 视频是一系列的图像,因此需要遍历所有的图像/帧,捕获并且显示int main()
{cv::VideoCapture capture(0);					// 只有一个相机cv::Mat img;while (1){capture.read(img);							// 读到img中// opencv提供的分类器cv::CascadeClassifier faceCascade;// 从加载模型(已经训练好的)faceCascade.load("Resources/haarcascade_frontalface_default.xml");// 检测文件是否加载成功if (faceCascade.empty()){std::cout << "XML file not loaded" << std::endl;}// 定义用于接收检测结果的std::vector<cv::Rect> faces;// 在输入图像中检测不同大小的对象,检测到的对象以矩形的列表的形式返回// 通过增加最近邻的值可以消除误报,但是过大将会导致漏检测// img/*输入*/, faces/*输出*/, 1.1/*比例因子*/, 3/*最近邻*/faceCascade.detectMultiScale(img, faces, 1.1, 3);// 绘制矩形for (int i = 0; i < faces.size(); i++){cv::rectangle(img, faces[i].tl(), faces[i].br(), cv::Scalar(255, 0, 255), 3);}cv::imshow("Vedio", img);					// 显示cv::waitKey(1);								// 延时1ms,数值越大,视频越慢}return 0;
}

自行测试

学习:4h上手C++版Opencv_哔哩哔哩_bilibili

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

归并排序算法

归并排序 1算法介绍 和选择排序一样&#xff0c;归并排序的性能不受输入数据的影响&#xff0c;但表现比选择排序好的多&#xff0c;因为始终都是O(n log n&#xff09;的时间复杂度。代价是需要额外的内存空间。归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用…

unity学习18:unity里的 Debug.Log相关

目录 1 unity里的 Debug.log相关 2 用Debug.DrawLine 和 Debug.DrawRay画线 2.1 画线 1 unity里的 Debug.log相关 除了常用的 Debug.Log&#xff0c;还有另外2个 Debug.Log("Debug.Log"); Debug.LogWarning("Debug.LogWarning"); Debug.LogErro…

c语言第一天

前言&#xff1a; bili视频2. 【初识C语言】第一个C语言项目_哔哩哔哩_bilibili 我感觉我意志不坚定&#xff0c;感觉要学网络安全&#xff0c;我又去专升本了&#xff0c;咋搞啊 多学一点是一点&#xff0c;我看到day1团队的人&#xff0c;一天学12个小时&#xff0c;年入2…

PyTorch DAY2: 搭建神经网络

如今&#xff0c;我们已经了解了 PyTorch 中张量及其运算&#xff0c;但这远远不够。本次实验将学会如何使用 PyTorch 方便地构建神经网络模型&#xff0c;以及 PyTorch 训练神经网络的步骤及方法。 知识点 PyTorch 构建神经网络Sequential 容器结构使用 GPU 加速训练模型保存…

2025 年 Java 最新学习资料与学习路线——从零基础到高手的成长之路

2025 年 Java 最新学习资料与学习路线——从零基础到高手的成长之路 大家好&#xff0c;欢迎来到我的频道&#xff01;今天我们要聊聊 Java ——这门陪伴了很多程序员成长的编程语言。无论你是编程新手&#xff0c;还是已经走了一段编程路&#xff0c;但还不确定如何深入学习 …

riscv架构下linux4.15实现early打印

在高版本linux6.12.7源码中&#xff0c;early console介绍&#xff0c;可参考《riscv架构下linux6.12.7实现early打印》文章。 1 什么是early打印 适配内核到新的平台&#xff0c;基本环境搭建好之后&#xff0c;首要的就是要调通串口&#xff0c;方便后面的信息打印。 正常流…

【论文阅读笔记】基于YOLO和ResNet深度卷积神经网络的结直肠息肉检测

作者&#xff1a;李素琴、吴练练、宫德馨、胡珊、陈奕云、朱晓云、李夏、于红刚 效果视频链接&#xff1a;https://www.xhnj.com/m/video/1008384.htm 小结 从算法的角度来说&#xff0c;作为2020发布的论文&#xff0c;使用的技术是比较落后的了。一个息肉检测项目&#xff0…

win32汇编环境,窗口程序中基础列表框的应用举例

;运行效果 ;win32汇编环境,窗口程序中基础列表框的应用举例 ;比如在窗口程序中生成列表框&#xff0c;增加子项&#xff0c;删除某项&#xff0c;取得指定项内容等 ;直接抄进RadAsm可编译运行。重点部分加备注。 ;以下是ASM文件 ;>>>>>>>>>>>…

Lora理解QLoRA

Parameter-Efficient Fine-Tuning (PEFT) &#xff1a;节约开销的做法&#xff0c;fine-tune少量参数&#xff0c;而不是整个模型&#xff1b; Low-Rank Adaptation (LoRA) &#xff1a;是PEFT的一种&#xff1b;冻结原参数矩阵&#xff0c;只更新2个小参数矩阵。 原文经过对比…

YOLOv5训练长方形图像详解

文章目录 YOLOv5训练长方形图像详解一、引言二、数据集准备1、创建文件夹结构2、标注图像3、生成标注文件 三、配置文件1、创建数据集配置文件2、选择模型配置文件 四、训练模型1、修改训练参数2、开始训练 五、使用示例1、测试模型2、评估模型 六、总结 YOLOv5训练长方形图像详…

基于微信小程序的电子点菜系统设计与实现(KLW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

Titans 架构中的记忆整合:Memory as a Context;Gated Memory;Memory as a Layer

Titans 架构中的记忆整合 Titans 架构中的记忆整合 Memory as a Context(MAC)变体:在处理长序列数据时,将序列分段,对于当前段 S ( t ) S^{(t)}

洛谷P3916 图的遍历

题目描述 给出 N 个点,M 条边的有向图&#xff0c;对于每个点 v&#xff0c;求 A(v) 表示从点 v 出发&#xff0c;能到达的编号最大的点。 输入格式 第 1 行 2 个整数 N,M&#xff0c;表示点数和边数。 接下来 M 行&#xff0c;每行 2 个整数 Ui,Vi​&#xff0c;表示边 (U…

【python】实现图像中的阴影去除 | 方案和代码

去除图像中的阴影是一项复杂的图像处理任务&#xff0c;尤其是当阴影区域与图像的其他部分混合时。阴影的存在会影响图像的颜色平衡和亮度&#xff0c;导致图像分析和理解的困难。 目录 一 安装依赖 二 函数 ① rgb2hsv ② hsv2rgb 三 实现图像中的阴影去除的方法 四 实…

记录一次 centos 启动失败

文章目录 现场1分析1现场2分析2搜索实际解决过程 现场1 一次断电,导致 之前能正常启动的centos 7.7 起不来了有部分log , 关键信息如下 [1.332724] XFS(sda3): Internal error xfs ... at line xxx of fs/xfs/xfs_trans.c [1.332724] XFS(sda3): Corruption of in-memory data…

文件操作:系统IO

文件操作 目录 基本概念Linux文件特点操作方式1-系统IO操作方式2-标准IO两种操作模式的对比 基本概念 什么是文件 简单的说&#xff0c;文件就是存储在硬件磁盘上的数据集合 文件通过什么来标识&#xff1f; 系统中在处理的文件&#xff08;读、写操作&#xff09;的时候…

ComfyUI-PromptOptimizer:文生图提示优化节点

ComfyUI-PromptOptimizer 是 ComfyUI 的一个自定义节点&#xff0c;旨在优化文本转图像模型的提示。它将用户输入的提示转换为更详细、更多样化、更生动的描述&#xff0c;使其更适合生成高质量的图像。无需本地模型。 1、功能 提示优化&#xff1a;优化用户输入的提示以生成…

windows 搭建flutter环境,开发windows程序

环境安装配置&#xff1a; 下载flutter sdk https://docs.flutter.dev/get-started/install/windows 下载到本地后&#xff0c;随便找个地方解压&#xff0c;然后配置下系统环境变量 编译windows程序本地需要安装vs2019或更新的开发环境 主要就这2步安装后就可以了&#xff0…

从玩具到工业控制--51单片机的跨界传奇【3】

在科技的浩瀚宇宙中&#xff0c;51 单片机就像一颗独特的星辰&#xff0c;散发着神秘而迷人的光芒。对于无数电子爱好者而言&#xff0c;点亮 51 单片机上的第一颗 LED 灯&#xff0c;不仅仅是一次简单的操作&#xff0c;更像是开启了一扇通往新世界的大门。这小小的 LED 灯&am…

构建一个简单的深度学习模型

构建一个简单的深度学习模型通常包括以下几个步骤&#xff1a;定义模型架构、编译模型、训练模型和评估模型。下面是一个使用Keras&#xff08;TensorFlow的高级API&#xff09;构建和训练一个简单的全连接神经网络&#xff08;也称为多层感知器&#xff0c;MLP&#xff09;的示…