opencv c++編程基礎

1、圖片的本質

圖像在 OpenCV 中的本質

在 OpenCV 中,圖像被表示為一個多維數組,其中每個元素對應于圖像中的單個像素。圖像的維度取決于其通道數和像素數。

  • **通道數:**圖像可以有多個通道,每個通道存儲圖像的不同信息。例如,彩色圖像通常有 3 個通道(紅色、綠色和藍色),而灰度圖像只有一個通道。
  • **像素數:**圖像的像素數決定了其寬度和高度。

圖像存儲方式

OpenCV 中的圖像通常以以下格式存儲:

  • **Mat:**這是 OpenCV 中最常用的圖像表示形式。Mat 是一個多維數組,可以存儲不同類型的圖像數據(例如,uint8、float32 等)。
  • **IplImage:**這是一個舊的圖像表示形式,在 OpenCV 2.0 之前使用。它與 Mat 類似,但有一些限制。

Mat 中圖像的存儲

Mat 中的圖像數據以行優先順序存儲。這意味著圖像的第一個維度對應于行,而第二個維度對應于列。對于一個 3 通道的彩色圖像,Mat 中的元素順序如下:

[B00, G00, R00, B01, G01, R01, ..., Bmn, Gmn, Rmn]

其中:

  • BGR 表示藍色、綠色和紅色通道
  • mn 是圖像的高度和寬度

通道的順序

OpenCV 中圖像的通道順序通常為 BGR(藍色、綠色、紅色)。這與其他一些圖像處理庫(如 PIL)中使用的 RGB 順序不同。

其他圖像存儲格式

除了 Mat 和 IplImage 之外,OpenCV 還支持其他圖像存儲格式,包括:

  • **UMat:**一種優化的 Mat,可利用 GPU 加速。
  • **cuda::GpuMat:**一種專用于 GPU 處理的 Mat。
  • **std::vector<uchar>:**一種使用標準 C++ 向量存儲圖像數據的格式。

2、Mat

從文件讀取圖片并顯示

#include <iostream>
#include "opencv2/core.hpp"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>using namespace std;
using namespace cv;int main(){Mat image;image = imread("firefox.png");      //imread()讀取圖片if(!image.empty()){imshow("1",image);              //imshow展示圖片,前面為展示名,后面為圖片。waitKey(0);}destroyAllWindows();return 0;
}

從文件讀取圖片并顯示

waitKey(0) 是 OpenCV 中的一個函數,用于等待用戶按下一個鍵。它有以下作用:

  • 暫停程序執行:waitKey(0) 會暫停程序執行,直到用戶按下一個鍵。這通常用于在顯示圖像或視頻時讓用戶有機會查看內容。
  • **獲取按鍵:**當用戶按下一個鍵時,waitKey(0) 會返回該鍵的 ASCII 碼。這可用于檢測用戶輸入并做出相應操作。
  • 無限等待:waitKey(0) 的參數為 0 表示無限等待。這意味著程序將一直暫停,直到用戶按下一個鍵。

使用示例:

cv::Mat image = cv::imread("image.png");cv::imshow("Image", image);cv::waitKey(0);

在上面的示例中,程序將暫停執行,直到用戶按下一個鍵。然后,程序將繼續執行,關閉圖像窗口并釋放資源。

注意:

  • waitKey(0) 是一個阻塞函數,這意味著它會阻止程序執行,直到用戶按下一個鍵。
  • 如果您不希望程序暫停執行,可以使用 waitKey(1),它將等待 1 毫秒的按鍵輸入。如果在此期間沒有按鍵輸入,程序將繼續執行。
  • waitKey(0) 通常用于交互式應用程序,例如圖像查看器或視頻播放器。

展示結果:

圖片大小resize函數

resize后保存為新圖片

#include <iostream>
#include "opencv2/core.hpp"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc.hpp>using namespace std;
using namespace cv;int main(){Mat image;image = imread("firefox.png");      //imread()讀取圖片if(!image.empty()){imshow("image",image);              //imshow展示圖片,前面為展示名,后面為圖片。waitKey(0);}// destroyAllWindows();Mat resize_image;resize(image, resize_image, Size(), 1, 0.5);     //resize()改變大小 前為高度 后為寬度if(!image.empty()){imshow("resize",resize_image);             waitKey(0);}imwrite("resize.png",resize_image);     //imwrite(文件名,圖片)寫入文件   需要指定擴展名,否則exceptiondestroyAllWindows(); return 0;
}

圖片旋轉

getRotationMatrix2D()和warpAffine()函數

 Mat rotated_image;double angle = 90;                                               //旋轉角度Point2f center(image.cols / 2.0, image.rows / 2.0);              //獲取旋轉中心Mat rotation_matix = getRotationMatrix2D(center, angle, 0.5);    //getRotationMatrix2D()計算旋轉矩陣 參數:旋轉中心、旋轉角度、放大倍數warpAffine(image, rotated_image, rotation_matix, image.size());  //warpAffine旋轉圖片  參數:原圖、目標圖片、旋轉矩陣、生成圖片的大小if(!rotated_image.empty()){imshow("rotate",rotated_image);             waitKey(0);}imwrite("rotate.png",rotated_image);   destroyAllWindows(); 

Point2f 是 OpenCV 中的一個結構,用于表示二維點。它包含兩個浮點成員:xy,分別表示點的橫坐標和縱坐標。

聲明:

struct Point2f {float x;float y;};

構造函數:

  • **Point2f():**創建一個默認構造的 Point2f,其中 xy 都為 0。
  • **Point2f(float x, float y):**創建一個 Point2f,其中 xy 設置為指定的值。

圖片平移

warpAffine()函數和平移矩陣

平移矩陣:

平移矩陣是一個 2x3 的仿射變換矩陣,

[ 1 0 tx ][ 0 1 ty ]

其中:

  • tx 是水平平移量。
  • ty 是垂直平移量。

為tx提供正值將使圖像向右移動,而負值將使圖像向左移動。

同樣,ty值為正值時,圖像會向下平移,而ty值為負值時,圖像會向上平移。

warpAffine()本質是仿射變換。

3、這里可以看到調整了大小或者平移過后窗口大小存在一些問題,:

可以使用 OpenCV 的 namedWindow() 函數來設置 imshow() 窗口的大小。

示例:

cv::namedWindow("Image", cv::WINDOW_NORMAL); // 創建一個可調整大小的窗口cv::imshow("Image", image);// 設置窗口大小cv::resizeWindow("Image", 640, 480);

參數:

  • **window_name:**窗口的名稱。
  • **flag:**一個標志,指定窗口的類型。WINDOW_NORMAL 創建一個可調整大小的窗口。

其他標志:

  • **WINDOW_AUTOSIZE:**窗口大小自動調整為圖像大小。
  • **WINDOW_FREERATIO:**窗口可以自由調整大小,而無需保持圖像的寬高比。
  • **WINDOW_FULLSCREEN:**窗口以全屏模式顯示。

注意:

  • namedWindow() 函數必須在 imshow() 函數之前調用。
  • 窗口大小只能在創建窗口后設置。
  • 窗口大小設置僅適用于可調整大小的窗口(即使用 WINDOW_NORMAL 標志創建的窗口)。

圖片拼接

在 OpenCV 中,可以使用 hconcat()vconcat() 函數水平和垂直拼接圖像。

水平拼接(并排):

cv::Mat image1 = cv::imread("image1.png");cv::Mat image2 = cv::imread("image2.png");cv::Mat拼接圖像;cv::hconcat(std::vector[cv::Mat](cv::Mat){image1, image2},拼接圖像);

垂直拼接(上下):

cv::Mat image1 = cv::imread("image1.png");cv::Mat image2 = cv::imread("image2.png");cv::Mat拼接圖像;cv::vconcat(std::vector[cv::Mat](cv::Mat){image1, image2},拼接圖像);

參數:

  • **images:**要拼接的圖像的向量。
  • **拼接圖像:**用于存儲拼接圖像的 Mat 對象。

注意:

  • 要拼接的圖像必須具有相同的通道數和深度。
  • hconcat()vconcat() 函數將自動調整圖像大小以匹配。
  • 拼接圖像的尺寸取決于要拼接的圖像的尺寸和拼接的方向。

圖片翻轉

在 OpenCV 中,可以使用 flip() 函數水平或垂直翻轉圖像。

水平翻轉:

cv::Mat image = cv::imread("image.png");cv::Mat flipped_image;// 水平翻轉cv::flip(image, flipped_image, 1);

垂直翻轉:

cv::Mat image = cv::imread("image.png");cv::Mat flipped_image;// 垂直翻轉cv::flip(image, flipped_image, 0);

參數:

  • **image:**要翻轉的圖像。
  • **flipped_image:**用于存儲翻轉后圖像的 Mat 對象。
  • **flipCode:**指定翻轉方向的標志。

flipCode 標志:

  • **0:**垂直翻轉
  • **1:**水平翻轉
  • **-1:**水平和垂直翻轉

注意:

  • 翻轉圖像不會修改原始圖像。
  • 翻轉圖像可能會導致圖像質量下降,尤其是在翻轉包含文本或其他非對稱特征的圖像時。

高斯模糊

在 OpenCV 中,可以使用 GaussianBlur() 函數對圖像應用高斯模糊。

示例

cv::Mat image = cv::imread("image.png");
cv::Mat blurred_image;// 高斯模糊
cv::GaussianBlur(image, blurred_image, cv::Size(5, 5), 0);

參數

**image:**要模糊的圖像。

**blurred_image:**用于存儲模糊后圖像的 Mat 對象。

**kernel_size:**模糊核的大小。它必須是一個奇數。

**sigmaX:**高斯核在 x 方向的標準偏差。如果為 0,則從 kernel_size 計算。

注意

高斯模糊是一種線性濾波器,它使用高斯核來平滑圖像。

高斯核是一個鐘形曲線,其中心權重最大,邊緣權重逐漸減小。

kernel_size 越大,模糊效果越強。

sigmaX 越大,模糊效果越明顯。

高斯模糊可能會導致圖像質量下降,尤其是邊緣和細節丟失。

4、完整代碼:

#include <iostream>
#include "opencv2/core.hpp"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc.hpp>using namespace std;
using namespace cv;int main(){Mat image;image = imread("firefox.png");      //imread()讀取圖片if(!image.empty()){namedWindow("image", cv::WINDOW_NORMAL);imshow("image",image);              //imshow展示圖片,前面為展示名,后面為圖片。resizeWindow("image", 640, 480);waitKey(0);}// destroyAllWindows();Mat resize_image;resize(image, resize_image, Size(), 1, 0.5);     //resize()改變大小 前為高度 后為寬度if(!resize_image.empty()){namedWindow("resize", cv::WINDOW_NORMAL);imshow("resize",resize_image);             resizeWindow("resize", 640, 480);waitKey(0);}imwrite("resize.png",resize_image);     //imwrite(文件名,圖片)寫入文件   需要指定擴展名,否則exception// destroyAllWindows(); Mat rotated_image;double angle = 90;                                               //旋轉角度Point2f center(image.cols / 2.0, image.rows / 2.0);              //獲取旋轉中心Mat rotation_matix = getRotationMatrix2D(center, angle, 0.5);    //getRotationMatrix2D()計算旋轉矩陣 參數:旋轉中心、旋轉角度、放大倍數warpAffine(image, rotated_image, rotation_matix, image.size());  //warpAffine旋轉圖片  參數:原圖、目標圖片、旋轉矩陣、生成圖片的大小if(!rotated_image.empty()){namedWindow("rotate", cv::WINDOW_NORMAL);imshow("rotate",rotated_image);    resizeWindow("rotate", 640, 480);         waitKey(0);}imwrite("rotate.png",rotated_image);   // destroyAllWindows(); Mat translated_image;                    float tx = float(image.rows) / 4;                           //平移距離 1/4 float ty = float(image.cols) / 4;                           //平移距離 1/4 float warp_values[] = { 1.0, 0.0, tx, 0.0, 1.0, ty };       //構建平移矩陣Mat translation_matrix = Mat(2, 3, CV_32F, warp_values);    //構建平移矩陣warpAffine(image, translated_image, translation_matrix, image.size());   //warpAffine平移圖片if(!translated_image.empty()){namedWindow("translated", cv::WINDOW_NORMAL);imshow("translated",translated_image); resizeWindow("translated", 640, 480);               waitKey(0);}imwrite("translated.png",translated_image);   destroyAllWindows(); Mat flipped_image_row;Mat flipped_image_col;flip(image, flipped_image_row, 1); //水平翻轉flip(image, flipped_image_col, 0); //垂直翻轉imshow("row",flipped_image_row);imshow("col",flipped_image_col);imshow("image",image);waitKey(0);destroyAllWindows(); Mat blurred_image;GaussianBlur(image, blurred_image, cv::Size(99,99), 0);imshow("blurred_image",blurred_image);waitKey(0);destroyAllWindows(); return 0;
}

簡單四宮格:

#include <opencv2/core/mat.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>using namespace cv;int main(){Mat image = imread("firefox.png");// Mat image_45;Mat image_90;Mat image_180;Mat image_270;// double angle_45 = 45;double angle_90 = 90;   double angle_180 = 180;double angle_270 = 270;                                            Point2f center(image.cols / 2.0, image.rows / 2.0);              // Mat rotation_matix_45 = getRotationMatrix2D(center, angle_45, 1.0);    // warpAffine(image, image_45, rotation_matix_45, image.size()); Mat rotation_matix_90 = getRotationMatrix2D(center, angle_90, 1.0);    warpAffine(image, image_90, rotation_matix_90, image.size()); Mat rotation_matix_180 = getRotationMatrix2D(center, angle_180, 1.0);    warpAffine(image, image_180, rotation_matix_180, image.size()); Mat rotation_matix_270 = getRotationMatrix2D(center, angle_270, 1.0);    warpAffine(image, image_270, rotation_matix_270, image.size()); Mat row_1;Mat row_2;Mat image_4x4;hconcat(std::vector<cv::Mat>{image, image_90},row_1);                 //橫向拼接hconcat(std::vector<cv::Mat>{image_270, image_180},row_2);            //縱向拼接vconcat(std::vector<cv::Mat>{row_1, row_2},image_4x4);imshow("4x4",image_4x4);waitKey(0);destroyAllWindows();return 0;
}

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

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

相關文章

一維掃描線,有多少對相交線段

D - Intersecting Intervals 目錄 正向&#xff1a; 反向&#xff1a; 正向&#xff1a; 從左往右掃描&#xff0c;記錄當前邊數。 來了新邊&#xff0c;它此刻與當前邊數相交&#xff0c;加到總數中。邊結束&#xff0c;當前邊數中減去即可。 const int maxn 5e55; int …

Uniapp橫豎屏切換讓某一個頁面只能橫屏或者豎屏

先看官方屬性 plus.screen.lockOrientation(default); // 默認橫豎屏切換 plus.screen.lockOrientation(portrait-primary);// 豎屏展示 plus.screen.lockOrientation(landscape-primary); // 強制橫屏簡單需求&#xff1a;允許橫豎屏切換 在 page.json增加以下代碼 "gl…

李廉洋:5.22黃金原油高位震蕩,今日最新行情分析策略。

黃金消息面分析&#xff1a;根據4月份的通脹數據&#xff0c;加拿大央行6月5日降息應該是“理所當然的”。加拿大的整體通貨膨脹率在4月份降至2.7%&#xff0c;為自2021年初以來的最低水平&#xff0c;核心CPI中加拿大央行的兩項首選數據均降至3%以下。加拿大央行在決定降息之前…

鴻蒙學習第一課--認識目錄結構

項目結構介紹 module.json5 src > main > module.json5&#xff1a;Stage模型模塊配置文件。主要包含HAP包的配置信息、應用/服務在具體設備上的配置信息以及應用/服務的全局配置信息。具體的配置文件說明&#xff0c;詳見module.json5配置文件。 資源分類和訪問 關于s…

vue使用asiox 下載后端返回的excel數據流

一、前端代碼 <template><div class"hello"><h1>{{ msg }}</h1><button style"color: brown" click"exportExcel">excel導出</button></div> </template><script> import axios from &q…

awk編輯器

目錄 工作原理 命令格式 普通格式 BEGIN格式 語句循環格式 awk常見的內建變量&#xff08;可直接用&#xff09; 按行打印行內容 統計行數量 按字段輸出文本 通過管道、雙引號調用 Shell 命令 awk編輯器是一種流編輯器 工作原理 逐行讀取文本,默認以空格或tab鍵為分…

二叉樹,先序遍歷、中序遍歷、后序遍歷和層序遍歷實現 C++

二叉樹基類聲明 template<typename T>class Tree{protected:Tree() default;virtual ~Tree() default;virtual const Tree& root()const 0;virtual Tree& root() 0;virtual const Tree& left()const 0;virtual const Tree& right()const 0;virtua…

java第十八課 —— 重載、可變參數

方法重載 基本介紹 java 中允許同一個類中&#xff0c;多個同名方法的存在&#xff0c;但要求形參列表不一致&#xff01; 比如&#xff1a;System.out.println(); out 是 PrintStream 類型 重載的好處 減輕了起名的麻煩減輕了記名的麻煩 注意事項和使用細節 方法名&…

【Vue】Vue2中的Vuex

目錄 Vuex介紹Vuex 中的核心概念 在vue2中使用Vuex安裝 Vuex創建一個 Vuex Store在 Vue 實例中使用 Vuex編寫 Vuex 的 state、mutations 和 actions在組件中使用 Vuex Vuex的核心State組件中獲取 Vuex 的狀態mapState 輔助函數對象展開運算符 Getter基本使用示例 通過屬性訪問通…

從多站點到多活,XEOS 對象數據容災能力再提升

近日&#xff0c; XSKY SDS V6.4 新版本發布&#xff0c;其中 XEOS V6.4 全新升級并完善了統一命名空間功能&#xff0c;更進一步增強和完善了異地容災方案&#xff0c;配合強一致代理讀&#xff0c;可以實現異地多活&#xff1b;同時大幅降低管理復雜度&#xff0c;有效降低容…

Nginx中的limit_req模塊和limit_conn模塊詳解

引言 在高流量場景下&#xff0c;良好的限流和連接控制策略至關重要&#xff0c;以防止服務器過載&#xff0c;確保服務穩定性和高可用性。Nginx 提供了 limit_req 和 limit_conn 模塊&#xff0c;用以實現請求頻率和并發連接數的限制。本文將詳細介紹這兩個模塊的生效階段和生…

TikTok電商帶貨特訓營,跟隨時代潮流,跨境掘金(8節課)

課程內容&#xff1a; 1-先導課 2-一、店鋪運營認知與思路 3-二、店鋪風控注意事項 4-三、美區Tiktok前期工作-1店鋪入駐模式 5-三、美區Tiktok前期工作-2指紋瀏覽器介紹 6-三、美區Tiktok前期工作-4綁定電話號碼 7-三、美區Tiktok前期工作-5添加倉庫地址 8-三、美區Ti…

GIS讀研與求職準備:植被定量遙感專業研0

本文介紹植被定量遙感專業研究生入學初期&#xff0c;為將來從事開發類工作所作求職準備的規劃路徑、方向選擇等方面的建議。 前面提到了&#xff0c;最近有很多師弟師妹詢問關于研究生方向選擇、求職準備等方面的問題。因為很多朋友的提問比較有共性&#xff0c;所以會在征得對…

【秒殺系統】從零開始打造簡易秒殺系統(一):防止超賣

【秒殺系統】從零開始打造簡易秒殺系統&#xff08;一&#xff09;&#xff1a;防止超賣 前言 大家好&#xff0c;好久不發文章了。&#xff08;快一個月了- -&#xff09;最近有很多學習的新知識想和大家分享&#xff0c;但無奈最近項目蠻忙的&#xff0c;很多文章寫了一半擱…

redis筆記1

1-nosql&#xff08;非關系型數據庫&#xff09; 定位緩存&#xff0c;提高數據讀寫速度&#xff0c;減輕對數據儲存與訪問壓力&#xff0c;不建議存敏感數據&#xff08;重要數據&#xff09;。 2-特征 &#xff08;1&#xff09;鍵值&#xff08;key-value&#xff09;型 &a…

【面試】Oracle JDK和Open JDK什么關系?

目錄 1. 起源與發展2. 代碼與許可3. 功能與組件4. 使用場景5. 版本更新與支持 1. 起源與發展 1.Oracle JDK是由Oracle公司基于Open JDK源代碼開發的商業版本。2.Open JDK是java語言的一個開源實現。 2. 代碼與許可 1.Oracle JDK包含了閉源組件&#xff0c;并根據二進制代碼許…

深入Java:JSON解析與操作的藝術

哈嘍&#xff0c;大家好&#xff0c;我是木頭左&#xff01; 一、初識JSON&#xff1a;數據格式的優雅舞者 在現代Web開發中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;以其輕量級和易于閱讀的特點成為了數據交換的首選格式。它基于JavaScript的一個…

用最通俗的話理解什么是協程

參考&#xff1a; 用最通俗的話理解什么是協程-CSDN博客

FreeRTOS_信號量_學習筆記

信號量的特性 消息隊列用于傳輸多個數據&#xff0c;但是有時候我們只需要傳遞狀態&#xff0c;這個狀態值需要用一個數值表示。套用隊列筆記中的流水線例子&#xff0c;可以理解為流水線上工件的數量。 信號&#xff1a;起通知作用 量&#xff1a;還可以用來表示資源的數量 當…

打印機手動雙面打印技巧

一、WORD和PDF &#xff08;1&#xff09;首先選擇要打印的頁面范圍&#xff0c;然后選擇僅奇數頁打印 &#xff08;2&#xff09;將打印完的紙張翻過來&#xff0c;白紙朝上&#xff0c;紙張的頭部先放入打印機 &#xff08;3&#xff09;選擇要打印的頁面范圍&#xff0c;然…