OpenCV | 入门

news2024/11/17 22:40:40

OpenCV | 入门

安装

参考教程

基础知识

V G A = 640 × 480 VGA = 640 \times 480 VGA=640×480
H D = 1280 × 720 HD = 1280 \times 720 HD=1280×720
F H D = 1920 × 1080 FHD = 1920 \times 1080 FHD=1920×1080
4 K = 3840 × 2160 4K = 3840 \times 2160 4K=3840×2160
这些都表示了固定的像素,例如 VGA,代表在宽度上 640 像素(px),在高度上 480 像素。我们可以把这些像素看成一个一个框。
对于黑白图像 Binary Image, 用 0 代表黑色,用 1 代表白色。

对于 8 位,可以表示 2 8 = 256 2^8 = 256 28=256 个级别,也就是 0 ~ 255。一个灰度图像(Gray Scale Image) 也就是 8 Bit or 256 Level 的。
OpenCV学习笔记——HSV颜色空间超极详解&inRange函数用法及实战

显示图像

图片与代码放在同个目录下。

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    /* Importing Images */
    string path = "../dog.jpeg";
    Mat img = imread(path);

    imshow("Image", img);
    waitKey(0);
}

播放视频

#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    string path = "../Megamind.avi";

    VideoCapture cap(path);

    Mat img;

    while(1)
    {
        cap.read(img);
        
        imshow("Image", img);

        waitKey(3); // 添加延时
    }

    return 0;
}

将图片转换为灰度图像

string path = "../dog.jpeg";
Mat img = imread(path);
Mat imgGray;

/* 转换图像颜色 */
cvtColor(img, imgGray, COLOR_BGR2GRAY);

imshow("Image", img);
imshow("Image Gray", imgGray);
waitKey(0);

模糊图像

Mat imgBlur;
GaussianBlur(img, imgBlur, Size(7, 7), 5, 0);
imshow("Image Blur", imgBlur);

边缘检测

Mat imgCanny;
Canny(imgBlur, imgCanny, 50, 150);
imshow("Image Canny", imgCanny);


对于 Canny 函数

void cv::Canny(InputArray image, OutputArray edges, double lowThreshold, double highThreshold, int apertureSize = 3);

/*
image:输入图像,应该是灰度图像。 
edges:输出图像,即检测到的边缘图像。 
lowThreshold:低阈值,用于双阈值检测。 
highThreshold:高阈值,用于双阈值检测。 
apertureSize:指定Sobel算子的大小,默认为3。
*/

图像膨胀

Mat imgDil;
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(imgCanny, imgDil, kernel);
imshow("Image Dilate", imgDil);


getStructuringElement 函数返回一个结构元素(卷积核)。

Mat kernel = cv2.getStructuringElement(a,b,c);

/*
a 设定卷积核的形状,不同卷积核(形状、大小)对图形的腐蚀、膨胀操作效果不同。
	MORPH_RECT(函数返回矩形卷积核)  
	MORPH_CROSS(函数返回十字形卷积核)  
	MORPH_ELLIPSE(函数返回椭圆形卷积核)
b 设定卷积核的大小
	用 (x, y) 表示,表示卷积核有 x 行 y 列。
c 表示描点的位置,一般 c = 1,表示位于中心。
*/

图像腐蚀

Mat imgErode;
erode(imgDil, imgErode, kernel);
imshow("Image Erode", imgErode);

调整图片大小

输出图片的尺寸

cout << img.size() << endl;


对其进行增大

Mat imgResize;

resize(img, imgResize, Size(640, 480));

imshow("Image Resize", imgResize);


如果使用比例进行缩小,缩小到 二分之一

resize(img, imgResize, Size(), 0.5, 0.5);

裁剪图片

用 Rect 裁剪一块矩形

Mat imgCrop;

Rect roi(300, 300, 250, 150); // x 坐标 y 坐标 宽度 高度
imgCrop = img(roi);

imshow("Image Crop", imgCrop);

创建图片

创建一张蓝色的图片

Mat img(512, 512, CV_8UC3, Scalar(255, 0, 0));

imshow("Image", img);

绘制图形

绘制圆圈

// White Image
Mat img(512, 512, CV_8UC3, Scalar(255, 255, 255));

circle(img, Point(256, 256), 155, Scalar(0, 69, 255));

imshow("Image", img);

增加圆圈的厚度
circle(img, Point(256, 256), 155, Scalar(0, 69, 255), 10);

填满圆圈
circle(img, Point(256, 256), 155, Scalar(0, 69, 255), FILLED);

绘制矩形

rectangle(img, Point(130, 226), Point(382, 286), Scalar(255, 255, 255), 3);
// 两个 Point 分别代表矩形左上角坐标和右下角坐标

将矩形填满
rectangle(img, Point(130, 226), Point(382, 286), Scalar(255, 255, 255), FILLED);

绘制一条线

line(img, Point(130, 296), Point(382, 296), Scalar(255, 255, 255), 2);

添加文字

putText(img, "Birdy's Workshop", Point(137, 262), FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 255));

给文字添加厚度
putText(img, "Birdy's Workshop", Point(137, 262), FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 255), 2);

Warp images

原图像:

int main()
{   
    string path = "../image/cards.jpg";

    float w = 250, h = 350;

    Mat img = imread(path);
    Mat matrix, imgWarp;

    Point2f src[4] = {{529, 142}, {779, 190}, {405, 395}, {674, 457}};
    Point2f dst[4] = {{0.0f, 0.0f}, {w, 0.0f}, {0.0f, h}, {w, h}};

    matrix = getPerspectiveTransform(src, dst);
    warpPerspective(img, imgWarp, matrix, Point(w, h));
 
    imshow("Image", img);
    imshow("Image Warp", imgWarp);

    waitKey(0);

    return 0;
}

圈出选中的四个角

for(int i = 0; i < 4; i ++)
    {
        circle(img, src[i], 10, Scalar(0, 0, 255), FILLED);
    }
 
imshow("Image", img);

颜色检测

原图像

HSV 颜色系统

Hue 色相
Saturation 饱和度
Value 色调、纯度

转换 HSV

将图像转换为 hsv 空间可以更容易识别颜色。

Mat imgHSV;

cvtColor(img, imgHSV, COLOR_BGR2HSV);

imshow("Image HSV", imgHSV);

Mask

Mat mask;

int hmin = 0, smin = 110, vmin = 153;
int hmax = 19, smax= 240, vmax = 255;

Scalar lower(hmin, smin, vmin);
Scalar upper(hmax, smax, vmax);
inRange(imgHSV, lower, upper, mask);

imshow("Image Mask", mask);


上述代码中的 hmin、smin、vim … 一系列的值如果通过每次手动修改去找到适合的就会非常麻烦。可以通过创建轨道的方式进行动态修改。

int main()
{
    string path = "../image/lambo.png";

    Mat img = imread(path);
    Mat imgHSV, mask;

    cvtColor(img, imgHSV, COLOR_BGR2HSV);

    int hmin = 0, smin = 110, vmin = 153;
    int hmax = 19, smax= 240, vmax = 255;

    namedWindow("Trackbars", (640, 200));
    createTrackbar("Hue Min", "Trackbars", &hmin, 179);
    createTrackbar("Hue Max", "Trackbars", &hmax, 179);
    createTrackbar("Sat Min", "Trackbars", &smin, 255);
    createTrackbar("Sat Max", "Trackbars", &smax, 255);
    createTrackbar("Val Min", "Trackbars", &vmin, 255);
    createTrackbar("Val Max", "Trackbars", &vmax, 255);

    while(1)
    {
        Scalar lower(hmin, smin, vmin);
        Scalar upper(hmax, smax, vmax);
        inRange(imgHSV, lower, upper, mask);

        imshow("Image", img);
        imshow("Image HSV", imgHSV);
        imshow("Image Mask", mask);

        waitKey(1);
    }

    return 0;
}


调节之后:

检测不同颜色物体

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    string path = "../image/shapes.png";

    Mat img = imread(path);
    Mat imgHSV, mask;

    int hmin = 0, smin = 0, vmin = 0;
    int hmax = 179, smax= 255, vmax = 255;
    
    cvtColor(img, imgHSV, COLOR_BGR2HSV);
    namedWindow("Trackbars", (640, 200));
    createTrackbar("Hue Min", "Trackbars", &hmin, 179);
    createTrackbar("Hue Max", "Trackbars", &hmax, 179);
    createTrackbar("Sat Min", "Trackbars", &smin, 255);
    createTrackbar("Sat Max", "Trackbars", &smax, 255);
    createTrackbar("Val Min", "Trackbars", &vmin, 255);
    createTrackbar("Val Max", "Trackbars", &vmax, 255);

    while(1)
    {
        Scalar lower(hmin, smin, vmin);
        Scalar upper(hmax, smax, vmax);
        inRange(imgHSV, lower, upper, mask);

        imshow("Image", img);
        imshow("Image HSV", imgHSV);
        imshow("Image Mask", mask);

        waitKey(1);
    }

    waitKey(0);

    return 0;
}


检测轮廓、形状

#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    string path = "../image/shapes.png";

    Mat img = imread(path);
    Mat imgGray, imgBlur, imgCanny, imgDil, imgErode; 

    cvtColor(img, imgGray, COLOR_BGR2GRAY);
    GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);
    Canny(imgBlur, imgCanny, 25, 75);
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
    dilate(imgCanny, imgDil, kernel);

    imshow("Image", img);
    imshow("Image Gray", imgGray);
    imshow("Image Blur", imgBlur);
    imshow("Image Canny", imgCanny);
    imshow("Image Dil", imgDil);

    waitKey(0);

    return 0;
}


当我们放大 ImgCanny 也就是边缘检测的图像,会发现三角形边有很明显的毛躁和缝隙。

而放大膨胀后的图像,发现这些毛躁和缝隙变少,所以一般用膨胀后的图像来作为边缘检测的图像。

绘制轮廓

#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

void getContours(Mat imgDil, Mat img)
{
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    drawContours(img, contours, -1, Scalar(255, 0, 255), 2);
}

int main()
{
    string path = "../image/shapes.png";

    Mat img = imread(path);
    Mat imgGray, imgBlur, imgCanny, imgDil, imgErode; 

    // Preprocessing
    cvtColor(img, imgGray, COLOR_BGR2GRAY);
    GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);
    Canny(imgBlur, imgCanny, 25, 75);
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
    dilate(imgCanny, imgDil, kernel);

    getContours(imgDil, img);

    imshow("Image", img);
    // imshow("Image Gray", imgGray);
    // imshow("Image Blur", imgBlur);
    // imshow("Image Canny", imgCanny);
    // imshow("Image Dil", imgDil);

    waitKey(0);

    return 0;
}


但是我们发现,小噪点也被勾勒了轮廓。
我们想去除这些噪点的轮廓。

打印每个图形面积

for(int i = 0; i < contours.size(); i ++)
    {
        int area = contourArea(contours[i]);
        cout << area << endl;
    }

通过输出每个图形的面积,我们发现,噪点面积为 185.

我们可以简单设置如果面积在 1000 以上才回绘制轮廓

void getContours(Mat imgDil, Mat img)
{
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	// drawContours(img, contours, i, Scalar(255, 0, 255), 2);

    for(int i = 0; i < contours.size(); i ++)
    {
        int area = contourArea(contours[i]);
        cout << area << endl;

        if(area > 1000) 
        {
            drawContours(img, contours, i, Scalar(255, 0, 255), 2);
        }
    }
}

可以发现噪点没有被绘制轮廓。

图像轮廓点进行多边形拟合

approxPolyDP 函数主要功能是把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合。

void getContours(Mat imgDil, Mat img)
{
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    
    vector<vector<Point>> conPoly(contours.size());

    for(int i = 0; i < contours.size(); i ++)
    {
        int area = contourArea(contours[i]);
        cout << area << endl;

        if(area > 1000) 
        {
            float peri = arcLength(contours[i], true);

            approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);

            drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);

            cout << conPoly[i].size() << endl;
        }
    }
}

可以看到它绘制了很多点,然后将它们连接,而不是绘制圆

输出每个图形点的个数:

图形边界矩形

void getContours(Mat imgDil, Mat img)
{
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

	vector<vector<Point>> conPoly(contours.size());
	vector<Rect> boundRect(contours.size());

    for(int i = 0; i < contours.size(); i ++)
    {
        int area = contourArea(contours[i]);
        cout << area << endl;

        if(area > 1000) 
        {
            float peri = arcLength(contours[i], true);

            approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);

            drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);

            cout << conPoly[i].size() << endl;

            boundRect[i] = boundingRect(conPoly[i]);
            rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
        }
    }
}

输出形状名称

void getContours(Mat imgDil, Mat img)
{
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

	vector<vector<Point>> conPoly(contours.size());
	vector<Rect> boundRect(contours.size());
    for(int i = 0; i < contours.size(); i ++)
    {
        int area = contourArea(contours[i]);
        cout << area << endl;

        string objectType;

        if(area > 1000) 
        {
            float peri = arcLength(contours[i], true);

            approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);

            drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);

            cout << conPoly[i].size() << endl;

            boundRect[i] = boundingRect(conPoly[i]);
            rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
        
            int objCor = (int)conPoly[i].size();

            if(objCor == 3) {
                objectType = "Tri"; // 如果点数为 3
            }
            else if(objCor == 4) {
                objectType = "Rect"; // 点数为 4
            }
            else {
                objectType = "Circle";
            }

            putText(img, objectType, {boundRect[i].x, boundRect[i].y - 5}, FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 255)); // 显示文本
        }
    }
}


但是上述代码知识简单将长方形和正方形都定义为矩形,那么该如何分辨长方形和正方形呢?
我们用宽高比来判断。

else if(objCor == 4) {
	// objectType = "Rect";
	float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height;
	if(aspRatio > 0.95 && aspRatio < 1.05)
		objectType = "Square";
	else
		objectType = "Rectangle";
}


OPENCV——C++版图像形状简单识别

人脸识别

#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    string path = "../image/test.png";

    Mat img = imread(path);

    CascadeClassifier faceCascade;
    faceCascade.load("../haarcascade_frontalface_default.xml");

    if(faceCascade.empty())
        puts("None!");
    
    vector<Rect> faces;
    faceCascade.detectMultiScale(img, faces, 1.1, 10);

    for(int i = 0; i < faces.size(); i ++)
    {
        rectangle(img, faces[i].tl(), faces[i].br(), Scalar(255, 0, 255), 3);
    }

    imshow("Image", img);
    waitKey(0);

    return 0;
}

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

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

相关文章

怎样的跨网软件,可以实现网间数据的安全收发?

网络隔离已是较为常见的网络安全保护措施&#xff0c;比如防火墙、网闸、VLAN&#xff0c;云桌面虚拟环境等方面进行隔离。像一些科技研发型企业&#xff0c;不仅仅是内外网隔离&#xff0c;甚至还划分办公网、研发网、测试网、生产网等&#xff0c;防止研发资料、设计资料等敏…

Windows Nginx 服务器部署并推流

环境 开发环境&#xff1a;windows 开发工具&#xff1a;ffmpeg、nginx、nginx-rmtp-module、vlc media player Nginx Nginx是一个高性能的HTTP和反向代理web服务器&#xff0c;并且支持rtmp&#xff0c;不过rtmp是作为一个nginx的一个模块。 对于linux系统&#xff0c;需要另…

使用Selenium破解滑动验证码的原理及解决思路

1、获取页面元素信息&#xff1a; 使用Selenium打开目标网页&#xff0c;并通过相关方法获取滑块、背景图等元素的位置和属性信息。可以使用Selenium提供的定位方法&#xff08;如xpath、CSS选择器等&#xff09;来找到这些元素。 可以使用find_element_by_xpath或find_elemen…

673. 最长递增子序列的个数(Leetcode)

文章目录 前言一、题目描述二、解题步骤1.小demo介绍2.动态规划1.状态表示2.状态转移方程3.初始化4.填表顺序5.返回值 三、代码编写总结 前言 在本篇文章中&#xff0c;我们将会讲到leetcode中673. 最长递增子序列的个数&#xff0c;我们将会用动态规划方式解决这道问题&#…

weditor安装的时候产生的问题

先放出来github的地址https://github.com/alibaba/web-editor&#xff0c;这个上面给了两种安装方式一种是&#xff1a; pip3 install -U weditor 这种方式会报错误&#xff0c; 具体原因我也不知道。那就采用第二种方式 git clone https://github.com/openatx/weditor pip3…

实体同城商家短视频获客,3天直播课,玩转实体商家私域,引爆门店增长

课程内容&#xff1a; 实体同城3天直播课【资料】 实体商家获客第一天 .mp4 实体商家获客第二天上.mp4 实体商家获客第二天,mp4 实体商家获客第三天.mp4 实体商家获客第4天.mp4 网盘自动获取 链接&#xff1a;https://pan.baidu.com/s/1lpzKPim76qettahxvxtjaQ?pwd0b8x…

【Linux】从零开始认识动静态库 -动态库

送给大家一句话&#xff1a; 我不要你风生虎啸&#xff0c; 我愿你老来无事饱加餐。 – 梁实秋 《我把活着欢喜过了》 ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ଘ(੭ˊᵕˋ)੭…

数据结构与算法学习笔记三---队列的链式存储表示和实现(C++)

目录 前言 1.队列的概念 2.队列的表示和实现 1.定义 2.初始化 ​编辑 3.销毁队列 4.清空队列 5.队列判空 6.队列长度 7.获取队头元素 8.入队 9.出队 10.遍历 11.完整代码 前言 这篇博客主要讲的是对队列的链式存储。 1.队列的概念 队列是一种访问受限的线性表。…

如何将一个VPS上的网站全部迁移至另外一个VPS服务器

最近我们老的VPS即将到期&#xff0c;由于近期Hostease的VPS活动力度较大&#xff0c;我们购买了Hostease的VPS&#xff0c;购买后需要将原服务器的所有网站迁移到Hostease提供的VPS中。在Hostease技术人员的帮助下&#xff0c;我们成功进行了迁移&#xff0c;下面我就介绍此次…

酷开科技丨母亲节,别让有爱瞬间轻易溜走

在母亲节这个充满温情的节日里&#xff0c;酷开科技以“健健康康才能长长久久”为主题&#xff0c;推出了一系列关怀活动&#xff0c;旨在通过科技的力量&#xff0c;提升母亲们的身体素质和生活质量&#xff0c;同时也为儿女们提供了表达孝心和关怀的机会。 酷开系统特别上线…

域基础-NTLM协议

简介 NTLM(New Technology LAN Manager)协议是微软用于Windows身份验证的主要协议之一。继SMB、LM协议之后微软提出了NTLM协议&#xff0c;这一协议安全性更高&#xff0c;不仅可以用于工作组中的机器身份验证&#xff0c;又可以用于域环境身份验证&#xff0c;还可以为SMB、H…

深入解析RedisSearch:全文搜索的新维度

码到三十五 &#xff1a; 个人主页 在当今的数据时代&#xff0c;信息的检索与快速定位变得尤为关键。Redis&#xff0c;作为一个高性能的内存数据库&#xff0c;已经在缓存和消息系统中占据了重要地位。然而&#xff0c;Redis并不直接支持复杂的搜索功能。为了填补这一空白&am…

Android AOSP Ubuntu源码编译电脑卡顿问题定位解决

文章目录 问题概述分析问题解决问题查看交换分区创建交换分区删除交换分区调整交换分区的活跃度 问题概述 开发SystemUI时&#xff0c;使用内存为16G的主机&#xff0c;Ubuntu 20.04的系统编译SystemUI的源码&#xff0c;编译的过程中发现电脑卡顿&#xff0c;鼠标不能移动。必…

渗透思考题

一&#xff0c;尝试登录。 客户端对密码进行哈希处理并缓存密码hash&#xff0c;丢弃实际的明文密码&#xff0c;然后将用户名发送到服务器&#xff0c;发起认证请求 密文存储位置&#xff1a;数据库文件位于C:WindowsSystem32configsam&#xff0c;同时挂载在注册表中的HKLMSA…

台阶仪测量膜厚原理及优势

台阶仪&#xff0c;也称为探针式轮廓仪或接触式表面轮廓测量仪&#xff0c;主要用于台阶高、膜层厚度、表面粗糙度等微观形貌参数的测量。 台阶仪的工作原理 台阶仪的核心部件是一个精密的触针或探针&#xff0c;它被安装在一个高度可调的支架上。当触针沿被测表面轻轻滑过时…

vue阶段案例,练习filter、map、forEach,双向绑定,三元表达式,以及图片滚动,文字跳动等等。

阶段案例 通过案例来练习双向绑定&#xff0c;三元表达式&#xff0c;以及图片滚动&#xff0c;文字跳动等等。 代码如下&#xff1a; <template><table class"bjtp" ><div class"title" >{{title}}</div><div class"s…

ACM实训冲刺第四天

【碎碎念】最近的任务有点繁重&#xff0c;所以考虑到实际情况&#xff0c;视频学习决定放置一段时间&#xff0c;重点是学校的实训练习题&#xff0c;对于我而言&#xff0c;目标不是优秀/良好&#xff0c;综合考虑我的实际情况&#xff0c;保佑我及格、顺利通过就可&#xff…

机器学习算法应用——神经网络回归任务、神经网络分类任务

神经网络回归任务&#xff08;4-3&#xff09; 神经网络回归任务&#xff0c;通常指的是使用神经网络模型进行回归分析。回归分析是一种统计学方法&#xff0c;用于研究一个或多个自变量&#xff08;预测变量&#xff09;与一个因变量&#xff08;响应变量&#xff09;之间的关…

node pnpm修改默认包的存储路径

pnpm与npm的区别 PNPM和NPM是两个不同的包管理工具。 NPM&#xff08;Node Package Manager&#xff09;是Node.js的官方包管理工具&#xff0c;用于安装、发布和管理Node.js模块。NPM将包安装在项目的node_modules目录中&#xff0c;每个包都有自己的依赖树。 PNPM&#xf…

c++ STL 之栈—— stack 详解

vector 是 stl 的一个关联容器,名叫“栈”&#xff0c;何为“栈”&#xff1f;其实就是一个数组&#xff0c;但有了数组何必还需栈&#xff0c;这是一个高深的问题。 一、简介 1. 定义 栈&#xff0c;是一个柔性数组&#xff08;可变长数组&#xff09;&#xff0c;可以变大变小…