opencv_C++學習筆記(入門30講)

文章目錄

  • 1.配置開發環境
  • 2.圖像讀取與顯示
  • 3.圖像色彩空間轉換
  • 4.圖像對象的創建與賦值
  • 5.圖像像素的讀寫操作
  • 6.圖像像素的算數操作
  • 7.滾動條-調整圖像亮度
  • 8.滾動條-調整對比度和亮度
  • 9.鍵盤響應操作
  • 10.圖像像素的邏輯操作
  • 11.圖像的通道分離和合并
  • 12.圖像色彩空間轉換
  • 13.圖像的像素值統計
  • 14.圖像幾何形狀繪制
  • 15.隨機數與隨機顏色
  • 16.多邊形填充與繪制
  • 17.鼠標操作與響應
  • 18.圖像像素類型轉換與歸一化
  • 19.圖像縮放與插值
  • 20.圖像翻轉
  • 21.圖像旋轉
  • 22.視頻文件攝像頭使用
  • 23.視頻處理與保存
  • 24.圖像直方圖
  • 25.二維直方圖
  • 26.直方圖均衡化
  • 27.圖像卷積和高斯模糊
  • 28.雙邊模糊
  • 29.人臉實時檢測

1.配置開發環境

配置開發環境提前需要安裝好Visual Studio和opencv包,這里可以單獨觀看視頻學習安裝。
以下過程參考鏈接: B站opencv快速入門30講-賈志剛

  1. 配置包含目錄
    這里需要注意上面的菜單欄選擇Release和x64,打開屬性管理器選擇Release|x64>VC++目錄>包含目錄。(可能由于Visual Studio版本的問題,這里沒有和視頻中相同的microsoft.cpp.x64.user文件(但是新建的相同文件名的文件會顯示已存在該文件,在項目中確實已經存在),因此直接對Release|x64屬性修改是一樣的)
    具體步驟:視圖》其他窗口》屬性管理器》Release | x64》屬性》VC++目錄》包含目錄》編輯》將opencv安裝包中的兩個目錄地址復制進去,如下圖所示:這樣包含目錄就配置好了。
    在這里插入圖片描述在這里插入圖片描述

  2. 配置庫目錄
    接下來配置庫目錄,點擊常規下面的庫目錄》編輯》如下圖所示將opencv安裝包的lib 目錄復制進去,點擊確定。這樣庫目錄就配置好了。
    在這里插入圖片描述

  3. 配置鏈接器
    接下來配置鏈接器:如下圖所示:屬性》鏈接器》輸入》附加依賴項》編輯》,在下圖中有兩個.lib 文件opencv_world460.lib 和opencv_world460d.lib,分別對應Release和Debug,切記勿將兩個文件同時寫進去。這里選擇opencv_world460.lib。點擊確定。這樣鏈接器配置完畢。
    在這里插入圖片描述
    在這里插入圖片描述
    在這里插入圖片描述

  4. 配置環境變量并重啟VS2022
    系統》高級系統設置》配置環境變量,將opencv安裝包里面的類似下圖的bin路徑添加進去,點擊確定。重啟VS。在這里插入圖片描述

配置環境變量并重啟VS2022

2.圖像讀取與顯示

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main(int argc, char ** argv){cv::Mat src = cv::imread("C/code/workspace/lena.jpg", IMREAD_GRAYSCALE);nameWindow("輸入窗口“, WINDOW_FREERATIO);if (src.empty()) {printf("could not load image...");return -1;}cv::imshow("輸入窗口”, src);cv::watiKey(0);destoryAllWindows();return 0;
}

代碼解釋:
#<opencv2/opencv.hpp> OpenCV庫預處理指令,包含了OpenCV庫的所用頭文件。
# C++標準庫預處理指令。該頭文件包含了C++庫中的輸入輸出流函數。
using namespace cv 這是openCV庫的命名空間。它將所有OpenCV庫中的函數都放在cv命名空間中,這樣可以通過cv:: 函數來調用它們。
suing namespace std 這是C++標準庫的命名空間,它將C++庫中的函數都放在std命名空間中,這樣可以通過std:: 函數來調用它們。
int main(int argc, char** argv) 這是程序主函數接受兩個參數,argc和argv,argc是一個整數,表示命令行參數的個數,argv是一個字符淑珍數組,表示命令行參數的指針。
cv::Mat src = cv::imread(“C/code/workspace/lena.jpg”, IMREAD_GRAYSCALE); cv::imread()是OpenCV讀取圖像的函數,將圖像讀取為灰度圖像,并將圖像存儲在cv::Mat 的src變量中。
nameWindow(“輸入窗口”,WINDOW_FREERATIO)這是OpenCV庫中創建窗口的函數指令,將創建一個名為“輸入窗口”窗口,并使用WINDOW_FREERATIO自動調整窗口大小。
cv::imshow(“輸入窗口”, src) 這是OpenCV中顯示圖像的函數,它將變量src顯示在“輸入窗口”中。
cv::waitKey(0) 這是OpenCV中的waitKey函數等待用戶按鍵的指令,它將等待用戶按下任意鍵,然后繼續執行。
destroyAllWindows() 這是OpenCV關閉所有窗口的指令。

3.圖像色彩空間轉換

這節學習如何創建頭文件,如何定義頭文件中的函數,以及如何在程序中調用自定義的頭文件函數

  1. 頭文件的創建
    創建頭文件:在項目文件下面的頭文件中創建一個新建項,名為xxxxx.h 的文件
    #include <opencv2/opencv.hpp>
    using namespace cv;
    class QuickDemo {public:void colorSpace_Demo(Mat& image);
    };
    
    代碼解釋:定義了一個名為QuickDemo 的類,public 是類的公共部分的開始, void colorSpace_Demo( )是QuickDemo類的成員函數,這個函數接受一個Mat類型的參數 image,用于存儲輸入的圖像。};是類的定義的結束。
  2. 定義頭文件函數
    頭文件中定義的類成員函數需要在源文件中創建一個名為 xxxxx.cpp 的文件
    #include "quickopencv.h"
    void QuickDemo::colorSpace_Demo(Mat& image) {Mat gray, hsv;cvtColor(image, hsv, COLOR_BGR2HSV);cvtColor(image, gray, COLOR_BGR2GRAY);imshow("HSV", hsv);imshow(“灰度”, gray);imwrite("C/code/workspace/hsv.jpg", hsv);imwrite("C/code/workspace/gray.jpg", gray);
    }
    
    代碼解釋:QuickDemo::colorSpace_Demo(Mat& image)): 這是QuickDemo類的成員函數colorSpace_Demo的聲明。cvtColor() 是OpenCV庫進行顏色空間轉化的指令。imwrite()這是OpenCV的imwrite函數將圖像保存到文件的指令。
    HSV(Hue, Saturation, Value)是一種顏色的表示方式,色相(Hue),飽和度(Saturation), 透明度(Value)
  3. 主函數文件
    主函數文件在源文件中 新建項為文件名 xxxxxx.cpp 的文件
    #include <opencv2/opencv.hpp>
    #inluce <iostream>
    #include "quickopencv"
    using namespace cv;
    using namespace std;
    int main(int argc, char ** argv){Mat src = cv::imread("C/code/workspace/lena.jpg");nameWindow("輸入窗口“, WINDOW_FREERATIO);if(src.empty()) {printf("could not load image...");return -1;}cv::imshow("輸入窗口”,src);QuickDemo qd;qd.colorSpace_Demo(src);cv::waitKey(0);destroyAllWindows();return 0;
    }
    

4.圖像對象的創建與賦值

這一節承接上一節的內容,需要在自定義的頭文件中添加類QuickDemo 的成員函數mat_creation_demo(), 同時需要在源文件夾下面的quickdemo.cpp 中定義函數Quick::mat_creation_demo() 的具體內容。本節中學習的關于OpenCV庫中的克隆、復制、賦值、創建空白圖像等都是在成員函數mat_creation_demo()中定義的。在執行程序時還需要再main.cpp 文件中調用mat_creation_demo()函數。
下面是關于成員函數的定義:

void QuickDemo::mat_creation_demo(Mat& image){Mat src = image;// 創建方法-克隆Mat m1 = src.clone();//復制Mat m2;src.copyTo(m2);//賦值法Mat m3 = srcl;//創建空白圖像Mat m4 = Mat::zeros(src.size(), src.type());Mat m5 = Mat::zeros(size(512, 512), CV_8UC3);imshow("窗口1", m1);imshow(“窗口2, m2);imshow("窗口3", m3);// 除上面的圖像對象外,還可以創建一個空白對像,然后賦值標量Mat m6, m7;m6 = image.clone();image.copyTo(m7);//創建單通道的空白圖像Mat m8 = Mat::zeros(Size(512, 512), CV_8UC1);//創建三通道空白圖像Mat m9 = Mat::zeros(Size(512, 512), CV_8UC3);//給三通道空白圖像賦標量值m9 = Scalar(0, 128, 64);std::cout << "width:" << m9.cols << "height:" << m9.rows << "channels:" << m9.channels() << std::endl;std::cou t  << m9 <<std::endl;

代碼解釋:上面的代碼中主要是最后兩行的輸出流需要注意,m9.cols:這是m9 對象的成員變量,表示圖像的寬度。m9.rows:這是m9 對象的成員變量,表示圖像的高度。m9.channels():這是m9 對象的成員變量,用于獲取圖像的通道數。std::cout:這是C++標準庫中的iostream流對象,用于輸出文本,<< :這是流對象的輸出操作符,用于將右邊的操作數(如變量m9.cols)輸出到流中。std::endl:這是iostream流對象的結束標記,用于輸出一個換行符,并刷新輸出緩沖區。

5.圖像像素的讀寫操作

第一種方法是通過數組坐標訪問每一像素,總體來看是使用了兩個for循環;同樣的,這里是在類成員是函數的詳細定義中,去定義這個像素的訪問。下面是第一種方法的代碼演示:

void QuickDemo::pixel_visit_demo(Mat& image) {int w = image.cols;int h = image.rows;int dims = image.channels();for (int row = 0; row < h; row++) {for (int col = 0; col < w; col++) {if (dims == 1) {  //灰度圖像int pv = image.at<uchar>(row, col);image.at<uchar>(row, col) = 255 - pv;}if (dims == 3) {  //彩色圖像Vec3b bgr = image.at<Vec3b>(row, col);image.at<Vec3b>(row, col)[0] = 255 - bgr[0];image.at<Vec3b>(row, col)[0] = 255 - bgr[1];image.at<Vec3b>(row, col)[0] = 255 - bgr[2];}}}imshow("像素讀寫演示", image);

第二種方法是通過指針的方式訪問每個像素,下面是代碼演示:

void QuickDemo::pixel_visit_demo(Mat& image) {int w = image.cols;int h = image.rows;int dims = image.channels();for (int row = 0; row < h; row++) {uchar* current_row = image.ptr<uchar>(row);for (int col = 0; col < w; col++) {if (dims == 1) {  //灰度圖像int pv = *current_row;*current_row++ = 255 - pv;}if (dims == 3) {  //彩色圖像*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;}}}imshow("像素讀寫演示", image);

代碼解釋:這里主要是需要理解指針的運用,image.ptr(row):這是OpenCV中的Mat對象image的成員函數ptr,它返回抑制指向圖像第row行的數據的指針。表示我們想要獲取的像素數據類型是8位無符號整數(uchar).插入一句額外的話,C語言之所以效率高,就是因為C可以像匯編一樣去操控內存。整形(int)是占用4個字節,基于32位的有符號整形。
下面是關于指針的代碼圖解
在這里插入圖片描述

6.圖像像素的算數操作

這節學習如何對圖像的像素進行加減乘除操作,下面通過代碼演示加深對圖像像素進行加減乘除的理解。

void QuickDemo::operators_demo(Mat &image){Mat dst = Mat::zeros(image.size(), image.type());Mat m = Mat::zeros(image.size(), image.type());//dst = image - Scalar(50, 50, 50);//dst = image + Scalar(50, 50 ,50);//mutiply(image, m, dst);// dst = image / Scalar(50, 50, 50);// imshow("圖像的算數操作",  dst);int w = image.cols;int h = image.rows;int dims = image.channels();for (int row = 0; row < h; row++){for (int col = 0; col < w; col++){Vec3b p1 = image.at<Vec3b>(row, col);Vec3b p2 = m.at<Vec3b>(row, col);dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);}}imshow("加法操作", dst);
}

代碼解釋:at(row, col)表示獲取指定位置的像素,獲得的p1 是一個有三個元素的數組,saturate_cast是將相加后的像素值轉換為8位無符號(uchar)的整數,以適應dst圖像的像素范圍。

7.滾動條-調整圖像亮度

這節學習通過滾動條,用戶可以在窗口中自行調整圖像的亮度,下面是代碼演示:

Mat src, dst, m;
int lightness = 20;
static void on_track(int, void*) {m = Scalar(lightness, lightness, lightness);add(src, m, dst);//subtract(src, m, dst);imshow("亮度調整", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image) {namedWindow("亮度調整", WINDOW_AUTOSIZE);dst = Mat::zeros(image.size(), image.type());m = Mat::zeros(image.size(), image.type());src = image;int max_value = 250;createTrackbar("Value Bar:", "亮度調整", &lightness, max_value, on_track);on_track(50, 0);
}	 

代碼解釋:這節的代碼和下一節一起進行解釋。

8.滾動條-調整對比度和亮度

這節學習在窗口中添加兩個滾動條,一個調整圖像的亮度,另一個調整圖像的對比度,下面是代碼演示:

static void on_lightness(int b, void* userdata){Mat image = *((Mat*)userdata);Mat dst = Mat::zeros(image.size(), image.type());Mat m = Mat::zeros(image.size(), image.type());addWeighted(image, 1.0, m, 0, b, dst);imshow("亮度與對比度調整",  dst);
}
static void on_contrast(int b, void* userdata){Mat image = *((Mat*)userdata);Mat dst = Mat::zeros(image.size(), image.type());Mat m = Mat::zeros(image.size(), image.type());double contrast = b / 100.0;addWeighted(image, contrast, m, 0.0, 0, dst);imshow("亮度與對比度調整",  dst);
}void QuickDemo::tracking_bar_demo(Mat &image){nameWindow("亮度與對比度調整", WINDOW_AUTOSIZE);int lightness = 50;int max_value = 250;int contrast_value = 100;createTrackbar("Value Bar:", "亮度與對比度調整“, &lightness,max_value, on_lightness, (void*)(&image));createTrackbar("Contrast Bar:", "亮度與對比度調整“, &contrast_value,200, on_contrast, (void*)(&image));on_lightness(50, &image);
}

代碼解釋:在回調函數on_lightness()中,static: 表示該函數是靜態的,只在當前文件中可見。除此之外,還有靜態變量,靜態函數,靜態類。定義了變量的周期,在靜態函數中,只在當前文件中可見,防止其他文件有重名的函數。void:表示函數的返回類型為空;on_lightness:是函數名;int b:表示亮度調整參數;void* userdata:一個指向用戶數據的指針,通常用于傳遞圖像數據;
((Mat)userdata): 將userdata指針轉換為Mat* 類型并解引用,獲取圖像數據。addWeighted(image, 1.0, m, 0, b, dst); addWeighted: OpenCV中的函數,用于圖像的加權疊加。該函數的公式為:dst = image * 1.0 + m * 0 + b,即 dst = image + b,實現了亮度的調整。
最后定義了一個名為tracking_bar_demo的函數,用于創建一個窗口并添加了兩個滑動條(Tackbar),分別用于調整圖像的亮度和對比度。createTrackbar: OpebCV中的函數,用于創建一個滑動條。Value Bar: :滑動條的標簽。&lightness: 指向亮度值的指針,滑動條的當前值。max_value: 滑動條的最大值。on_lightness: 回調函數,當滑動條值改變時調用。(void*)(&image): 傳遞給回調函數的用戶數據,即圖像數據

9.鍵盤響應操作

這節學習通過鍵盤按鍵對圖像進行操作并顯示操作后的結果

void QuickDemo::key_demo(Mat& image) {Mat dst = Mat::zeros(image.size(), image.type());;while (true) {int c = waitKey(100);if (c == 27) {//Escbreak;}if (c == 49) {//Key#1std::cout << "you enter Key#1" << std::endl;cvtColor(image, dst, COLOR_BGR2GRAY);}if (c == 50) {// Key#2std::cout << "you enter Key#2" << std::endl;cvtColor(image, dst, COLOR_BGR2HSV);}if (c == 51) {//Key#3std::cout << "you enter Key#3" << std::endl;dst = image + Scalar(0, 128, 0);}//std::cout << c << std::endl;imshow("鍵盤響應", dst);}
}

代碼解釋:需要注意的是函數waitKey()返回的數據類型,總體上代碼不難。

10.圖像像素的邏輯操作

這節學習創建兩個圖像,對這兩個圖像進行與、或、非 操作;下面是代碼演示:

void QuickDemo::bitwise_demo(Mat& image) {Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);imshow("m1", m1);imshow("m2", m2);Mat dst;//Mat dst = ~image;//bitwise_not(image, dst);//bitwise_or(m1, m2, dst);bitwise_xor(m1, m2, dst);imshow("像素位操作", dst);
}

代碼解釋:rectangle() 是OpenCV庫中的函數,在圖像上繪制一個填充的矩形。m1表示目標圖像,即在m1上進行繪制,Rect() 這是矩形的參數,用于確定矩形的大小和位置;Scalar()這是矩形的顏色,-1表示矩形的厚度,這里就表示對矩形進行填充,除此之外還有其他參數,例如0,1,2;LINE_8這是繪制矩形時使用的線條類型,LINE_8表示8連通線型。0:這是可選的坐標縮放因子。

11.圖像的通道分離和合并

這節學習將RGB圖像的三個通道分離,并以單獨的紅色,綠色和藍色進行顯示;這是通道分離,通道合并時,學習如何將兩個任意的通道進行合并并顯示出來。下面時代碼演示:

void QuickDemo::channels_split_demo(Mat& image) {std::vector<Mat> mv;split(image, mv);imshow("藍色", mv[0]);imshow("綠色", mv[1]);imshow("紅色", mv[2]);Mat dst;mv[1] = 0;mv[2] = 0;merge(mv, dst);imshow("藍色", dst);int from_to[] = { 0, 2, 1, 1, 2, 0 };mixChannels(&image, 1, &dst, 1, from_to, 3);imshow("通道混合", dst);
}

代碼解釋:split() 函數用于將圖像分離成三個通道并存儲在mv變量中,這樣根據數組的操作可以對單獨的每個通道進行顯示,merge() 函數用于將兩個圖像進行合并,合并前將其余的兩個通道的數值置零就可以以單獨的紅、藍、綠進行顯示;最后用到一個通道混合的函數mixChannels(),mixChannels是OpenCV庫中的一個函數,void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs);
用于將輸入圖像的某些通道賦值到輸出圖像的某些通道中。const Mat* src是輸入圖像數組,size_t nsrcs是輸入圖像的數量,Mat* dst輸出圖像數組,可以是一個或多個圖像。 size_t ndsts是輸出圖像數量。const int* fromTo:一個數組,指定輸入和輸出通道的映射關系。 size_t npairs是數組中映射對的數量。

12.圖像色彩空間轉換

這節學習如何從純色的背景中扣出前景然后對背景顏色進行轉換。需要注意的是背景顏色必須是純色的。下面是代碼演示以及實驗結果圖。

void QuickDemo::inrange_demo(Mat& image){Mat hsv;cvtColor(image, hsv, COLOR_BGR2HSV);Mat mask;inRange(hsv, Scalar(36, 43, 46), Scalar(77, 255, 255), mask);imshow("mask", mask);Mat redback = Mat::zeros(image.size(), image.type());redback = Scalar(40, 40, 200);bitwise_not(mask, mask);imshow("mask", mask);image.copyTo(redback, mask);imshow("roi區域提取", redback);
}

代碼解釋:inRange()是OpenCV庫中的函數,用于在HSV顏色空間中進行顏色閾值處理。具體來說,它將圖像中的像素值與給定的范圍進行比較,并將符合條件的像素設置為白色(255), 不符合條件的像素設置為黑色(0)。HSV顏色空間將顏色分解為色調(Hue)、飽和度(Saturation)和亮度(Value)三個分量;在上述代碼中hsv是輸入的圖像,Scalar(36, 43, 46): 是下限閾值,這里的閾值根據HSV顏色空間能夠進行查詢獲得,這里的三個數是綠色的閾值下限。Scalar(77, 255, 255)是綠色的閾值上限。mask:輸出圖像,是一個二值化的圖像,在這個圖像中符合顏色范圍的像素值為255,不符合的像素值為0。后面將掩碼取反操作,即前景圖像的像素值從原來的0變為255,背景像素值從原來的255變為0;接下來使用image.copyTo(redback, mask);這里使用掩碼復制掩碼中像素值為255的redback像素值。這里更深入的理解需要理解copyTo()函數。

13.圖像的像素值統計

這節學習如何計算圖像各通道的均值和方差。下面是代碼演示:

void QuickDemo::pixel_statistic_demo(Mat& image) {double minv, maxv;Point minLoc, maxLoc;std::vector<Mat>mv;split(image, mv);for (int i = 0; i < mv.size(); i++) {minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());std::cout <<"No.channels: "<< i <<"min value : " << minv << "max value : " << maxv << std::endl;}Mat mean, stddev;meanStdDev(image, mean, stddev);std::cout << "means:" << mean << std::endl;std::cout<< "stddev:" << stddev << std::endl;
}

代碼解釋:首先定義了兩個Point類型的變量分別命名為minLoc, mavLoc;;其次定義了一個std::vector類型的變量mv,其元素類型為Mat ,這里的mv可以用于存儲多個圖像或矩陣數據。.Point是OpenCV庫中定義的一個類,通常用于表示圖像中的二維坐標點(x, y)。minMaxLoc()是OpenCV庫中的函數,用于在給定的圖像或矩陣中查找最小值和最大值及其位置。minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat()); ,mv[i]:是輸入的數據,&minv這是指向double類型的指針,用于存儲找到的最小值。&minLoc這是指向Point類型的指針,用于存儲最小值的位置,Mat(): 這是一個空的Mat對象,表示掩碼(mask).如果不需要使用掩碼,可以傳遞一個空的Mat對象。掩碼用于指定在哪些區域中進行最小值和最大值的查找。meanStdDev是OpenCV中的函數。用于計算給定圖像的均值和標準差。

14.圖像幾何形狀繪制

這節學習在圖像上繪制或者填充矩形、圓形、橢圓形、線條等,下面是代碼演示:

void QuickDemo::darwing_demo(Mat& image) {Rect rect;rect.x = 250;rect.y = 150;rect.width = 100;rect.height = 100;Mat bg = Mat::zeros(image.size(), image.type());rectangle(image, rect, Scalar(0, 0, 255), 2, 8, 0);circle(image, Point(350, 400), 50, Scalar(255, 0, 0), -1, 8, 0);line(image, Point(100, 100), Point(200, 200), Scalar(255, 255, 0));RotatedRect rrt;rrt.center = Point(200, 200);rrt.size = Size(100, 200);rrt.angle = 90;ellipse(image, rrt, Scalar(0, 0, 255), 2, 8);imshow("矩形", image);
}

代碼解釋:Rect是OpenCV庫中定義的一個類,用于表示矩形區域。Rect rect這行代碼聲明了一個Rect類型的變量。rectangle() 函數用于在圖像上繪制一個矩形。2: 表示矩形邊框的厚度,如果設置為負數矩形會被填充。8表示8連接線,0表示旋轉角度。circle() 函數用于在圖像上繪制一個圓形。Point(100, 100): 這是Point類型的對象,表示圓心的位置。50:表示圓的半徑。line() 函數用于在圖像上繪制一條直線。 RotatedRect是OpenCV庫中的函數用來繪制橢圓。

15.隨機數與隨機顏色

這節學習如何生成隨機數并且根據隨機種子在創建的圖像中畫隨機線條。下面是代碼演示:

void QuickDemo::random_drawing() {Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);int w = canvas.cols;int h = canvas.rows;RNG rng(12345);while (true) {int c = waitKey(100);if (c == 27) {break;}int x1 = rng.uniform(0, w);int y1 = rng.uniform(0, h);int x2 = rng.uniform(0, w);int y2 = rng.uniform(0, h);int b = rng.uniform(0, 255);int g = rng.uniform(0, 255);int r = rng.uniform(0, 255);//canvas = Scalar(0, 0, 0);line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, LINE_AA, 0);imshow("隨機繪制演示", canvas);}
}

代碼解釋:RNG rng(12345):這行代碼創建了一個隨機數生成器對象rng,并使用12345作為隨機種子,隨機種子是一個初始值,用于初始化隨機數生成器的狀態,相同的種子會產生相同的隨機數序列。隨機種子的作用是確保每次運行程序時,如果使用相同的種子,生成的隨機數序列是相同的。可以確保每次運行程序時生成的隨機數序列是可重復的。

16.多邊形填充與繪制

這節學習如何繪制多邊形:下面是代碼是演示:

void QuickDemo::polyline_drawing_demo() {Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);Point p1(100, 100);Point p2(350, 100);Point p3(450, 280);Point p4(320, 450);Point p5(80, 400);std::vector<Point>pts;pts.push_back(p1);pts.push_back(p2);pts.push_back(p3);pts.push_back(p4);pts.push_back(p5);//polylines(canvas, pts, true, Scalar(0, 0, 255), 8, 8, 0);//fillPoly(canvas, pts, Scalar(255, 255, 0), LINE_AA, 0);std::vector<std::vector<Point>>contours;contours.push_back(pts);drawContours(canvas, contours, -1, Scalar(255, 0, 0), -1);imshow("多邊形繪制", canvas);
}

代碼解釋:pts.push_back()將五個點添加到向量pts中,polyline() 函數是OpenCV中用于繪制多邊形的函數,canvas:繪制畫布。pts:點向量;true:表示多邊形是閉合的。fillPoly函數用于填充多邊形。drawContours()函數是OpenCV庫中繪制輪廓的函數。

17.鼠標操作與響應

這節學習通過鼠標繪制矩形提取圖像中的感興趣區域(ROI),下面是代碼演示:

Point sp(-1,-1);
Point ep(-1,-1);
Mat temp;
static void on_draw(int event, int x, int y, int flags, void* userdata){Mat image = *((Mat*)userdata);if(event == EVENT_LBUTTONDOWN){sp.x = x;sp.y = y;std::cout<<"start point:"<<sp<<sts::endl;}else if(event == EVENT_LBUTTONUP){ep.x = x;ep.y = y;int dx = ep.x - ep.x;int dy = ep.y - ep.y;if(dx>0 && dy>0){Rect box(sp.x, sp.y, dx, dy);rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);imshow("鼠標繪制", image);imshow("ROI區域", image(box));}else if(event ==EVENT_MOUSEMOVE){if(sp.x>0 && sp.y>0){ep.x = x;ep.y = y;int dx = ep.x - ep.x;int dy = ep.y - ep.y;if(dx>0 && dy>0){Rect box(sp.x, sp.y, dx, dy);temp.copyTo(image);rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);inshow("鼠標繪制", image);}}}
}
void QuickDemo::mouse_drawing_demo(Mat& image){nameWindow("鼠標繪制", WINDOW_AUTOSIZE);setMouseCallback("鼠標繪制”, on_draw, (void*)(&image));imshow("鼠標繪制", image);temp = image.clone();
}

代碼解釋:static void on_draw(int event, int x, int y, int flags, void* userdata){ 這行代碼定義了一個名為 on_draw的靜態函數,該函數在繪制事件發生時被調用。函數的參數包括:event: 表示繪制事件類型。當用戶點擊鼠標左鍵時,事件類型為EVENT_LBUTTONDOWN。flags:表示事件標志,userdata: 表示用戶數據,在這個例子中是一個指向Mat類型的指針,表示要繪制圖像。void QuickDemo::mouse_drawing_demo(Mat& image){ 這行代碼定義了一個名為mouse_drawing_demo的函數,該函數用于實現鼠標繪制的功能,setMouseCallback()函數是OpenCV庫中的函數,為鼠繪制窗口設置鼠標回調函數。on_draw是回調函數的名稱,(void*)(&image)是將圖像地址傳遞給回調函數,以便在回調函數中使用。

18.圖像像素類型轉換與歸一化

這節學習將圖像通整數類型轉換為浮點數數類型并進行顯示

void QuickDemo::norm_demo(Mat& image) {Mat dst;std::cout << image.type() << std::endl;image.convertTo(image, CV_32F);std::cout << dst.type() << std::endl;   // CV_8UC3, CV_32FC3normalize(image, dst, 1.0, 0, NORM_MINMAX);std::cout << dst.type() << std::endl;imshow("圖像數據歸一化", dst);
}

代碼解釋:這段代碼首先將圖像通過.convertTo()函數轉換為32位浮點數類型。然后通過 歸一化函數normlize()將圖像歸一化并存儲在dst中,歸一化的方式是NORM_MINMAX,最后顯示歸一化后的圖像數據dst。

19.圖像縮放與插值

這節學習圖像的縮放和插值操作,內容相對簡單。下面是代碼演示:

void QuickDemo::resize_demo(Mat& image) {Mat zoomin, zoomout;int h = image.rows;int w = image.cols;resize(image, zoomin, Size(w / 2, h / 2), 0, 0, INTER_LINEAR);imshow("zoomin", zoomin);resize(image, zoomout, Size(w * 1.5, h * 1.5), 0, 0, INTER_LINEAR);imshow("zoomout", zoomout);
}

代碼解釋:這里記住resize()函數就可以實現對圖像的縮放。

20.圖像翻轉

這節學習圖像的翻轉,只需要使用flip() 函數改變其參數就能實現圖像的水平翻轉、上下翻轉、對角線翻轉。代碼相對簡單。

void QuickDemo::flip_demo(Mat& image) {Mat dst;//flip(image, dst, 0);//上下翻轉//flip(image, dst, 1);//左右翻轉flip(image, dst, -1); //對角線翻轉,180°旋轉imshow("圖像翻轉", dst);
}

21.圖像旋轉

這節學習對圖像實現旋轉,圖像旋轉是通過仿射變換實現的,圖像旋轉后的高寬會發生變換,新的高寬通過下面圖示方式進行計算;
在這里插入圖片描述
下面是代碼演示:

void QuickDemo::rotate_demo(Mat& image) {Mat dst, M;int w = image.cols;int h = image.rows;M = getRotationMatrix2D(Point2f(w / 2, h / 2), 45, 1.0);double cos = abs(M.at<double>(0, 0));double sin = abs(M.at<double>(0, 1));int nw = cos * w + sin * h;int nh = sin * w + cos * h;M.at<double>(0, 2) = M.at<double>(0, 2) + (nw / 2 - w / 2);M.at<double>(1, 2) = M.at<double>(1, 2) + (nh / 2 - h / 2);warpAffine(image, dst, M, Size(nw, nh), INTER_LINEAR, 0, Scalar(255, 255, 255));imshow("旋轉演示", dst);
}

代碼解釋:getRotationMatrix2D()是OpenCV庫中的函數,它的功能是生成一個二維的旋轉矩陣,Point2f類型的對象,表示旋轉的中心點,45表示旋轉的角度,1.0表示旋轉的縮放因子。M是旋轉矩陣,從旋轉矩陣中取出cos seta 和 sin seta,接下來重新計算高寬,然后將旋轉中心值重新賦值給M矩陣,組后通過warpAffine()函數進行旋轉放射變換。

22.視頻文件攝像頭使用

這節學習如何調用電腦攝像頭實時顯示攝像頭內容以及如何讀取視頻文件,對讀取到的視頻內容也可以使用圖像處理中的一些處理進行顯示,例如灰度變換、HSV、摳圖等。下面是代碼演示:

void QuickDemo::video_demo(Mat& image) {VideoCapture capture(0);  // 讀出視頻文件capture(../video/xxx.mp4)Mat frame;while (true) {capture.read(frame);flip(frame, frame, 1);if (frame.empty()) {break;}imshow("視頻", frame);//TODO: do something...int c = waitKey(10);if (c == 27) {break;}}//releasecapture.release();
}

代碼解釋:VideoCapture是OpenCV中用于視頻捕獲的類,capture(0)表示從默認攝像頭捕獲視頻,Mat是OpenCV中用于存儲圖像數據的類。frame是一個Mat對象,用于存儲圖像數據的類。

23.視頻處理與保存

這節學習如何獲取讀取到的視頻屬性,例如高寬、視頻幀總數、每秒的幀數(FPS)等。最后學習如何保存視頻。下面是代碼演示:

void QuickDemo::video_demo(Mat& image) {VideoCapture capture("C:/code/workspace/data/video/dance.mp4");  // 讀出視頻文件capture(../video/xxx.mp4) 讀取攝像頭capture(0)int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);int count = capture.get(CAP_PROP_FRAME_COUNT);double fps = capture.get(CAP_PROP_FPS);std::cout << "fram width:" << frame_width << std::endl;std::cout << "fram height:" << frame_height << std::endl;std::cout << "Number of frames:" << count << std::endl;std::cout << "FPS:" <<fps<< std::endl;VideoWriter writer("C:/code/workspace/data/video/test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);Mat frame;while (true) {capture.read(frame);flip(frame, frame, 1);if (frame.empty()) {break;}namedWindow("視頻", WINDOW_NORMAL);resizeWindow("視頻", 800, 600);imshow("視頻", frame);//colorSpace_Demo(frame);writer.write(frame);//TODO: do something...int c = waitKey(10);if (c == 27) {break;}}//releasecapture.release();writer.release();
}

代碼解釋:獲取視頻的高寬等屬性用capture.get()函數,保存視頻文件時,VideoWriter是OpenCV庫中用于視頻寫入的類。writer是VideoWriter對象的名稱。capture是一個VideoCapture對象,用于視頻捕獲。write 是 VideoWriter 類的一個成員函數,用于將一幀圖像寫入到視頻文件中。

24.圖像直方圖

這節學習繪制rgb圖像三個通道的直方圖曲線,并將它們可視化在一張畫布上,下面是代碼演示:

void QuickDemo::Histogram_demo(Mat& image){//三通道分離std::vector<Mat> bgr_plane;split(image, bgr_plane);//定義參數變量const int channels[1] = {0};const int bins[1] = {256};float hranges[2] = {0, 255};const float* ranges[1] = {hranges};Mat b_hist;Mat g_hist;Mat r_hist;//計算Blue、Green、Red通道的直方圖calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);//顯示直方圖int hist_w = 512;int hist_h = 400;int bin_w = cvRound((double)hist_w / bins[0]);   //每個bin的寬度Mat histImage = Mat::zeros(histImage.rows, NORM_MINMAX, -1, Mat());Mat histImage = Mat::zeros(histImage.rows, NORM_MINMAX, -1, Mat());Mat histImage = Mat::zeros(histImage.rows, NORM_MINMAX, -1, Mat());//繪制直方圖曲線for (int i = 1; i<bins[0];i++){line(histImage, Point(bin_w*(i-1), hist_h-cvRound(b_hist.at<float>(i-1))),Point(bin_w*(i), hist_h -cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);line(histImage, Point(bin_w*(i-1), hist_h-cvRound(g_hist.at<float>(i-1))),Point(bin_w*(i), hist_h -cvRound(g_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);line(histImage, Point(bin_w*(i-1), hist_h-cvRound(r_hist.at<float>(i-1))),Point(bin_w*(i), hist_h -cvRound(r_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);//顯示直方圖nameWindow("Histogram Demo", WINDOW_AUTOSIZE);imshow("Histogram Demo", histImage);

代碼解釋:cvRound是OpenCV中的一個函數,用于將浮點數四舍五入為最接近的整數。這里關于線段的起始坐標還沒有搞清楚,

25.二維直方圖

代碼演示:

void QuickDemo::Histogram_2d_demo(Mat& image) {//2D直方圖Mat hsv, hs_hist;cvtColor(image, hsv, COLOR_BGR2HSV);   // H取值范圍是(0,180),S和V的取值范圍是(0,255)int hbins = 30, sbins = 32;int hist_bins[] = { hbins, sbins };float h_range[] = { 0, 180 };float s_range[] = { 0, 256 };const float* hs_ranges[] = { h_range, s_range };int hs_channels[] = { 0,1 };calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false);double maxVal = 0;minMaxLoc(hs_hist, 0, &maxVal, 0, 0);int scale = 10;Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);for (int h = 0; h < hbins; h++) {for (int s = 0; s < sbins; s++) {float binVal = hs_hist.at<float>(h, s);int intensity = cvRound(binVal * 255 / maxVal);rectangle(hist2d_image, Point(h * scale, s * scale),Point((h + 1) * scale - 1, (s + 1) * scale - 1), Scalar::all(intensity), -1);}}applyColorMap(hist2d_image, hist2d_image,COLORMAP_JET);imshow("H-S Histogram", hist2d_image);imwrite("C:/code/workplace/data/image/his2d.jpg", hist2d_image);
}

26.直方圖均衡化

原理:統計直方圖 》歸一化直方圖》累計直方圖》區間轉換
直方圖均衡化只能對單通道灰度圖像進行均衡化,如果對彩色圖像進行均衡化可以將彩色圖像轉換到HSV色彩空間然后對V通道的亮度進行直方圖均衡化。

void QuickDemo::histogram_eq_demo(Mat& image){Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);Mat dst;equalizeHist(gray, dst);imshow("直方圖均衡化", dst);
}

27.圖像卷積和高斯模糊

這節學習對圖像進行卷積操作和使用高斯核函數對圖像進行模糊處理,下面是代碼演示:

void QuickDemo::blur_demo(Mat& image) {Mat dst;blur(image, dst, Size(13, 13), Point(-1, -1));imshow("圖像模糊", dst);
}void QuickDemo::gaussian_blur_demo(Mat& image) {Mat dst;GaussianBlur(image, dst, Size(5, 5), 15);imshow("高斯模糊", dst);
}

代碼解釋:卷積操作使用blur() 函數,GaussianBlur() 是高斯模糊的函數。

28.雙邊模糊

雙邊模糊(Bilateral blur)是一種圖像處理技術,旨在模糊圖像中的細節,同時保留邊緣的清晰度,從而防止邊緣變得模糊或失真。與傳統的高斯模糊不同,雙邊模糊考慮了像素之間的空間距離和像素值之間的差異。具體來說,它利用了一個像素值相似性函數,這個函數在像素之間的距離較大時減小,從而保留了邊緣的銳利度。因此,雙邊模糊常用于需要在保留細節的同時進行圖像平滑處理的應用場景,如圖像去噪或者一些圖像特效的實現中。

void QuickDemo::bifilter_demo(Mat& image) {Mat dst;bilateralFilter(image, dst, 0, 100, 10);imshow("雙邊模糊", dst);
}

29.人臉實時檢測

這節通過加載訓練好的模型文件調用攝像頭 或者加載視頻文件實現人臉的實時檢測,在實現該項目時需要用到兩個文件,這兩個文件觀看b站視頻OpenCV與C++入門30講相應的視頻獲得下載地址,下面是代碼演示:

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;int main(int argc, char** argv) {;std::string pf_file_path_path = "C:/code/workspace/model/opencv_face_detector_uint8.pb";std::string pbtxt_file_path = "C:/code/workspace/model/opencv_face_detector.pbtxt";cv::dnn::Net net = cv::dnn::readNetFromTensorflow(pf_file_path_path, pbtxt_file_path);VideoCapture cap(0);cv::Mat frame;while (true) {cap.read(frame);if (frame.empty()) {break;}cv::Mat blob = cv::dnn::blobFromImage(frame, 1.0, Size(300, 300), cv::Scalar(104, 177, 123), false, false);net.setInput(blob);cv::Mat probs = net.forward();// 1x1xNx7cv::Mat detectMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>());for (int row = 0; row < detectMat.rows; row++) {float conf = detectMat.at<float>(row, 2);if (conf > 0.5) {float x1 = detectMat.at<float>(row, 3) * frame.cols;float y1 = detectMat.at<float>(row, 4) * frame.rows;float x2 = detectMat.at<float>(row, 5) * frame.cols;float y2 = detectMat.at<float>(row, 6) * frame.rows;cv::Rect box(x1, y1, x2 - x1, y2 - y1);cv::rectangle(frame, box, cv::Scalar(0, 0, 255), 2, 8);}}cv::imshow("OpenCV4.6DNN人臉檢測演示", frame);char c = waitKey(1);if (c == 27) {break;}	}cv::waitKey(0);cv::destroyAllWindows();return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/41613.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/41613.shtml
英文地址,請注明出處:http://en.pswp.cn/web/41613.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

阿里云存儲的降本增效與運維

小浩負責公司存儲架構層&#xff0c;需要確保存儲層不會成為公司業務系統的性能瓶頸&#xff0c;讓數據讀寫達到最佳性能。那么小浩可以從哪些方面著手優化性能呢&#xff1f;他繼續求助系統架構師大雷。 小浩&#xff1a;雷哥&#xff0c;PD反饋公司系統最近響應很慢&#xff…

HTTP模塊(一)

HTTP服務 本小節主要講解HTTP服務如何創建服務&#xff0c;查看HTTP請求&響應報文&#xff0c;還有注意事項說明&#xff0c;另外講解本地環境&Node環境&瀏覽器之間的鏈路圖示&#xff0c;如何提取HTTP報文字符串&#xff0c;及報錯信息查詢。 創建HTTP服務端 c…

lspci

【原】Linux之PCIE三種空間解析 PCIe學習筆記——2.PCIe配置空間 PCIE學習&#xff08;2&#xff09;PCIE配置空間詳解 開發者分享 | 使用 lspci 和 setpci 調試 PCIe 問題 b : 字節 w&#xff1a;word L&#xff1a; 4byte

LLM - 詞表示和語言模型

一. 詞的相似度表示 (1): 用一系列與該詞相關的詞來表示 (2): 把每個詞表示一個獨立的符號(one hot) (3): 利用該詞上下文的詞來表示該詞 (3): 建立一個低維度的向量空間&#xff0c;用深度學習方法將該詞映射到這個空間里(Word Embedding) 二&#xff1a;語言模型 (1): 根…

Postman中數據文件的高效使用:測試自動化與數據驅動測試實踐

摘要 Postman 是一個強大的 API 開發工具&#xff0c;它不僅支持 API 的設計、開發和測試&#xff0c;還提供了數據驅動測試的功能。通過使用數據文件&#xff0c;我們可以模擬不同的測試場景&#xff0c;實現測試的自動化和重復執行。本文將詳細介紹如何在 Postman 中使用數據…

PHP-實例-CSRF

1 需求 按照用途分類&#xff1a; 會話&#xff08;會話ID和會話令牌 二選一&#xff09; 會話ID&#xff1a;服務器側自動生成&#xff0c;自動存儲在cookie中&#xff0c;需要在服務器側存儲會話令牌&#xff1a;服務器側手動生成&#xff0c;手動存儲在cookie中&#xff0…

7月07日,每日信息差

第一、6 月份&#xff0c;北京、上海、廣州和深圳的新建商品住宅成交量分別環比增加 21%、66%、48% 和 38%&#xff0c;均創年內新高 第二、2024 年世界人工智能大會上&#xff0c;上海向四家企業發放了首批無駕駛人智能網聯汽車示范應用許可&#xff0c;這些企業可以在浦東部…

Redis源碼整體結構

一 前言 Redis源碼研究為什么先介紹整體結構呢?其實也很簡單,作為程序員的,要想對一個項目有快速的認知,對項目整體目錄結構有一個清晰認識,有助于我們更好的了解這個系統。 二 目錄結構 Redis源碼download到本地之后,對應結構如下: 從上面的截圖可以看出,Redis源碼一…

52-5 內網代理2 - LCX端口轉發(不推薦使用LCX)

環境搭建: 本地開3臺虛擬機:kali(必須)、windows2012與2008 (可換成其他windows虛擬機) kali - 網絡配置成橋接模式 windows2012 - 設置兩個網卡,NAT與橋接模式 注意:windows2012要關閉防火墻,要不然其他主機ping不通 關閉防火墻后再開啟遠程桌面連接 windwos20…

去O化神器 Exbase

隨著去O化進程推動&#xff0c;很多舊業務依賴的oracle數據庫&#xff0c;都需要實現做數據庫的替換&#xff0c;當下能很好兼容Oracle&#xff0c;并實現異構數據庫之間轉換的工具并不多。這里給大家推薦一個商業工具數據庫遷移工具exbase&#xff08;北京海量&#xff09;&am…

昇思MindSpore 25天學習打卡營|day18

DCGAN生成漫畫頭像 在下面的教程中&#xff0c;我們將通過示例代碼說明DCGAN網絡如何設置網絡、優化器、如何計算損失函數以及如何初始化模型權重。在本教程中&#xff0c;使用的動漫頭像數據集共有70,171張動漫頭像圖片&#xff0c;圖片大小均為96*96。 GAN基礎原理 這部分原…

想知道你的電腦能不能和如何升級RAM嗎?這里有你想要的一些提示

考慮給你的電腦增加更多的RAM,但不確定從哪里開始?本指南涵蓋了有關升級Windows PC或筆記本電腦中RAM的所有信息。 你需要升級RAM嗎 在深入研究升級RAM的過程之前,評估是否需要升級是至關重要的。你是否經歷過系統滯后、頻繁的BSOD錯誤或應用程序和程序突然崩潰?這些癥狀…

從零開始的python學習生活

pycharm部分好用快捷鍵 變量名的定義 與之前學習過的語言有所不同的是&#xff0c;python中變量名的定義更加的簡潔 such as 整形。浮點型和字符串的定義 money50 haha13.14 gaga"hello"字符串的定義依然是需要加上引號&#xff0c;也不需要寫&#xff1b;了 字符…

Django 常見的操作符

在filter() 方法&#xff0c;exclude() 方法中使用大于&#xff0c;小于&#xff0c;模糊匹配等操作符。 常見的操作符如下&#xff1a; 操作符含義示例等于Book.objects.filter(price10)! 或 __ne不等于用于查找字段不等于特定值的記錄。但更常用exclude()方法。__gt大于用于…

React Redux使用@reduxjs/toolkit的hooks

關于redux的學習過程需要幾個官網&#xff0c;有redux官網&#xff0c;React Redux官網和Redux Toolkit的官網。 其中后者的中文沒有找到&#xff0c;不過其中的使用在React Redux官網的快速入門中有介紹。 現在一般不使用connect借接口了。 對于借助Redux Toolkit的React Redu…

Linux GUN(gcc/g++) 版本升級教程

Linux gcc/g 升級命令: // 查看當前安裝的版本 ll /usr/bin/gcc* ll /usr/bin/g*// 更新源 sudo apt update // 安裝新版本 sudo apt install g-10 gcc-10 // 應用新的版本 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10 sudo update-altern…

【網站推薦】Developer Roadmaps 開發者學習路線

你是否想學習某門技術而苦苦找不到學習路線。本文推薦一個網站&#xff0c;解決學習路徑問題。 roadmap.sh 旨在創建路線圖、指南和其他教育內容&#xff0c;以幫助指導開發人員選擇路徑并指導他們的學習。 技術路線包括了前端后端安卓iosUI設計等內容&#xff0c;一些技術比如…

信息安全三要素

文章目錄 安全三要素 CIA機密性完整性可用性參考資料 安全三要素 CIA 安全三要素&#xff0c;也被稱為信息安全的CIA三要素&#xff0c;是確保信息和系統安全的核心原則。它們分別是&#xff1a; 機密性&#xff08;Confidentiality&#xff09;&#xff1a;保護數據不能泄露…

antdesignvue對話框用戶可移動并縮放

原貼 輕松搞定Ant Design Modal對話框拖拽縮放 - ByteZoneX社區https://www.bytezonex.com/archives/IFRuoJhd.html Ant Design 模態對話框&#xff1a;實現拖拽縮放功能 **子 Ant Design 是一個流行的前端 UI 框架&#xff0c;提供了一系列實用的組件&#xff0c;包括模態對…

ESP32CAM物聯網教學02

ESP32CAM物聯網教學02 物聯網門鎖 小智來到姑姑家門口&#xff0c;按了門鈴&#xff1b;還在公司上班的姑姑用電腦給小智開了門&#xff0c;讓他先進屋休息。小智對物聯網門鎖產生了興趣&#xff1a;什么是物聯網&#xff1f;為什么這么厲害&#xff1f; 初識物聯網 我們在百…