OpenCV圖像變換與處理實戰(zhàn)方法記錄
前言
在計算機視覺的絢麗舞臺上,OpenCV 無疑是一顆耀眼的明星,它賦予開發(fā)者操控圖像、挖掘視覺信息的超強能力。在正式深入那些令人驚嘆的代碼實例前,咱們先來夯實理論基礎(chǔ),為后續(xù)實操筑牢根基。
一、OpenCV 基礎(chǔ)與圖像處理概覽
OpenCV(Open Source Computer Vision Library),開源計算機視覺庫,猶如一座裝滿圖像處理 “神器” 的百寶箱。歷經(jīng)多年迭代、無數(shù)開發(fā)者打磨,它橫跨多平臺,用 C++、Python 等熱門語言編寫接口,貼合不同編程習(xí)慣,攬下計算機視覺八成基礎(chǔ)任務(wù),從簡單圖像讀取、存儲,到復(fù)雜目標(biāo)檢測、圖像識別,統(tǒng)統(tǒng)不在話下。
圖像處理本質(zhì)是對圖像像素的精心雕琢。圖像存于計算機里,像整齊排列的 “像素方陣”,每個像素懷揣顏色、亮度信息。咱做圖像處理,就是巧妙改變這些像素屬性。像調(diào)亮度,是給像素亮度值做加法;改顏色,是調(diào)配紅、綠、藍分量。手段不同,目的一致:讓圖像契合特定需求,或美輪美奐,或信息精準(zhǔn)。
二、圖像變換理論精析
(一)重映射(Remapping)
重映射堪稱圖像坐標(biāo)的 “乾坤大挪移”。正常圖像像素按行列規(guī)則站位,重映射打破常規(guī),依自定義映射規(guī)則給像素 “搬家”。核心原理是新建兩張和原圖像同尺寸 “坐標(biāo)圖”(src_x、src_y),記錄新位置,好比導(dǎo)游圖,指引像素 “遷移” 方向。這操作實用性拉滿,制造波浪、扭曲特效時大顯身手,讓畫面瞬間靈動。
(二)縮放(Scaling)
縮放直白說就是給圖像 “放大縮小”。數(shù)學(xué)上,按比例因子(scale_x、scale_y)改變行列像素數(shù)量,近的像素合并變小圖,間隔插值變 “長胖” 成大圖。插值算法是關(guān)鍵,常見線性插值(cv::INTER_LINEAR),像經(jīng)驗老到的裁縫,憑周邊像素信息,算出新增像素 “恰當(dāng)臉色”,保圖像平滑過渡。
(三)旋轉(zhuǎn)(Rotation)
旋轉(zhuǎn)讓圖像優(yōu)雅 “轉(zhuǎn)身”。先鎖定旋轉(zhuǎn)中心,多為圖像幾何中心,再用旋轉(zhuǎn)矩陣(由 cv::getRotationMatrix2D 生成)做 “旋轉(zhuǎn)指令”。這矩陣蘊含旋轉(zhuǎn)角度、縮放比例信息,結(jié)合仿射變換(cv::warpAffine),像素依指令乖乖就位,畫面流暢旋動,毫無違和 “暈車感”。
三、圖像增強與特征提取理論
(一)顏色變換(Color Conversion)
顏色空間多如繁星,常見 RGB、HSV、灰度等。RGB 重色彩呈現(xiàn),HSV 便顏色調(diào)整,灰度則聚焦亮度信息,拋棄色彩冗余。像轉(zhuǎn)灰度圖,用 cv::cvtColor 一鍵 “褪色”,按人眼亮度感知規(guī)則,加權(quán)融合 RGB 值,提取關(guān)鍵亮度,利于后續(xù)處理,還能降數(shù)據(jù)量、提處理速度。
(二)邊緣檢測(Edge Detection)
邊緣是圖像 “骨架”,藏關(guān)鍵輪廓信息。邊緣檢測算法像敏銳偵探,緊盯像素灰度突變處。Canny 算法是王牌,設(shè)低、高雙閾值,梯度超 “高線” 鎖定邊緣;在 “低線” 與 “高線” 間,看連接情況甄別;低過 “低線”,直接 pass。經(jīng)非極大值抑制、雙閾值篩選,精準(zhǔn)揪出邊緣,給目標(biāo)識別、圖像分割鋪好路。
(三)高斯模糊(Gaussian Blur)
現(xiàn)實圖像常帶噪聲,像老照片劃痕、數(shù)碼噪點。高斯模糊化身 “美顏磨皮師”,用高斯函數(shù)生成權(quán)重核,中心像素權(quán)重高、周邊遞減,加權(quán)平均周邊像素值,模糊圖像、柔化噪聲,讓畫面細膩干凈,為后續(xù)精準(zhǔn)處理清障。
(四)圖像銳化(Image Sharpening)
銳化是模糊 “克星”,找回圖像丟失細節(jié)。原理是強化高頻分量,弱化低頻??刻刂凭矸e核(如文中 3x3 核)卷積圖像,中心像素 “突出”,周邊反向調(diào)節(jié),反差凸顯邊緣細節(jié),照片、掃描文檔處理后清晰度飆升。
(五)顏色反轉(zhuǎn)(Color Inversion)
顏色反轉(zhuǎn)堪稱圖像 “鏡像世界”,簡單粗暴按位取反像素值。白變黑、黑變白,各顏色分量翻轉(zhuǎn),特定藝術(shù)創(chuàng)作、負(fù)片效果模擬時,輕松拿捏氛圍感。
三、實例分析
1. 定義常量 M_PI
#ifndef M_PI #define M_PI 3.14159265358979323846 // 如果未定義 M_PI,則手動定義 #endif
這段代碼的目的是確保在編譯過程中,如果 M_PI
常量未被定義,則手動定義它為圓周率的值。這在一些情況下是必要的,因為不同的編譯器和環(huán)境可能對某些常量的定義有所不同。
2. 重映射圖像創(chuàng)建波形效果
void wave(const cv::Mat& img, cv::Mat& res, const std::string& wave_type, double amplitude, double frequency) { cv::Mat src_x(img.rows, img.cols, CV_32F); cv::Mat src_y(img.rows, img.cols, CV_32F); for (int i = 0; i < img.rows; i++) { for (int j = 0; j < img.cols; j++) { src_x.at<float>(i, j) = static_cast<float>(j); double wave_value = 0.0; if (wave_type == "sine") { wave_value = amplitude * sin(frequency * static_cast<double>(j)); // 正弦波 } else if (wave_type == "cosine") { wave_value = amplitude * cos(frequency * static_cast<double>(j)); // 余弦波 } else if (wave_type == "triangle") { wave_value = amplitude * (2.0 / M_PI) * asin(sin(frequency * static_cast<double>(j))); // 三角波 } else if (wave_type == "sawtooth") { wave_value = amplitude * (2.0 * (j / static_cast<double>(img.cols)) - 1.0); // 鋸齒波 } src_y.at<float>(i, j) = static_cast<float>(i + wave_value); } } cv::remap(img, res, src_x, src_y, cv::INTER_LINEAR); }
這個函數(shù)用于創(chuàng)建不同類型的波形效果,通過重映射圖像的像素坐標(biāo)來實現(xiàn)。它接受輸入圖像 img
、輸出圖像 res
、波形類型 wave_type
、振幅 amplitude
和頻率 frequency
作為參數(shù)。
首先,創(chuàng)建兩個與輸入圖像大小相同的矩陣 src_x
和 src_y
,分別用于存儲重映射后的 x 和 y 坐標(biāo)。然后,通過雙層循環(huán)遍歷輸入圖像的每個像素。對于每個像素,將 src_x
中的對應(yīng)值設(shè)置為當(dāng)前像素的 x 坐標(biāo),并根據(jù) wave_type
的不同計算出波形的值 wave_value
。最后,將 src_y
中的對應(yīng)值設(shè)置為當(dāng)前像素的 y 坐標(biāo)加上波形值。
最后,使用 cv::remap
函數(shù)根據(jù) src_x
和 src_y
矩陣對輸入圖像進行重映射,得到輸出圖像 res
。
3. 縮放圖像
void scale(const cv::Mat& img, cv::Mat& res, double scale_x, double scale_y) { cv::resize(img, res, cv::Size(), scale_x, scale_y, cv::INTER_LINEAR); }
這個函數(shù)用于縮放圖像。它接受輸入圖像 img
、輸出圖像 res
、水平縮放比例 scale_x
和垂直縮放比例 scale_y
作為參數(shù)。
使用 cv::resize
函數(shù)對輸入圖像進行縮放,將輸出圖像的大小設(shè)置為輸入圖像的大小乘以縮放比例。這里使用 cv::INTER_LINEAR
插值方法,以獲得較為平滑的縮放效果。
4. 旋轉(zhuǎn)圖像
void rotate1(const cv::Mat& img, cv::Mat& res, double angle) { cv::Point2f center(img.cols / 2.0, img.rows / 2.0); cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0); cv::warpAffine(img, res, rot, img.size()); }
這個函數(shù)用于旋轉(zhuǎn)圖像。它接受輸入圖像 img
、輸出圖像 res
和旋轉(zhuǎn)角度 angle
作為參數(shù)。
首先,計算圖像的中心坐標(biāo)。然后,使用 cv::getRotationMatrix2D
函數(shù)創(chuàng)建一個旋轉(zhuǎn)矩陣 rot
,該矩陣將圖像繞中心旋轉(zhuǎn)指定的角度。最后,使用 cv::warpAffine
函數(shù)根據(jù)旋轉(zhuǎn)矩陣對輸入圖像進行仿射變換,得到輸出圖像 res
。
5. 顏色變換(灰度圖)
void grayscale(const cv::Mat& img, cv::Mat& res) { cv::cvtColor(img, res, cv::COLOR_BGR2GRAY); }
這個函數(shù)用于將彩色圖像轉(zhuǎn)換為灰度圖像。它接受輸入圖像 img
和輸出圖像 res
作為參數(shù)。
使用 cv::cvtColor
函數(shù)將輸入圖像從 BGR 顏色空間轉(zhuǎn)換為灰度顏色空間,得到輸出圖像 res
。
6. 邊緣檢測
void edge_detection(const cv::Mat& img, cv::Mat& res) { cv::Canny(img, res, 100, 200); }
這個函數(shù)用于進行邊緣檢測。它接受輸入圖像 img
和輸出圖像 res
作為參數(shù)。
使用 cv::Canny
函數(shù)對輸入圖像進行邊緣檢測,該函數(shù)接受輸入圖像、輸出圖像、低閾值和高閾值作為參數(shù)。邊緣檢測算法會根據(jù)像素的梯度強度來確定是否為邊緣像素,如果像素的梯度強度大于高閾值,則被認(rèn)為是邊緣像素;如果像素的梯度強度小于低閾值,則被認(rèn)為不是邊緣像素;如果像素的梯度強度在低閾值和高閾值之間,則根據(jù)其與邊緣像素的連接情況來確定是否為邊緣像素。
7. 高斯模糊
void gaussian_blur(const cv::Mat& img, cv::Mat& res) { cv::GaussianBlur(img, res, cv::Size(5, 5), 0); }
這個函數(shù)用于對圖像進行高斯模糊處理。它接受輸入圖像 img
和輸出圖像 res
作為參數(shù)。
使用 cv::GaussianBlur
函數(shù)對輸入圖像進行高斯模糊,該函數(shù)接受輸入圖像、輸出圖像、模糊核大小和標(biāo)準(zhǔn)差作為參數(shù)。這里使用的模糊核大小為 cv::Size(5, 5)
,標(biāo)準(zhǔn)差為 0,表示由函數(shù)自動計算標(biāo)準(zhǔn)差。
8. 圖像銳化
void sharpen(const cv::Mat& img, cv::Mat& res) { cv::Mat kernel = (cv::Mat_<float>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); cv::filter2D(img, res, img.depth(), kernel); }
這個函數(shù)用于對圖像進行銳化處理。它接受輸入圖像 img
和輸出圖像 res
作為參數(shù)。
首先,定義一個 3x3 的銳化內(nèi)核 kernel
。然后,使用 cv::filter2D
函數(shù)對輸入圖像進行卷積操作,該函數(shù)接受輸入圖像、輸出圖像、圖像深度和卷積內(nèi)核作為參數(shù)。這里將輸入圖像與銳化內(nèi)核進行卷積,得到輸出圖像 res
,從而實現(xiàn)圖像銳化的效果。
9. 顏色反轉(zhuǎn)
void invert_colors(const cv::Mat& img, cv::Mat& res) { cv::bitwise_not(img, res); }
這個函數(shù)用于對圖像進行顏色反轉(zhuǎn)處理。它接受輸入圖像 img
和輸出圖像 res
作為參數(shù)。
使用 cv::bitwise_not
函數(shù)對輸入圖像進行按位取反操作,即將每個像素的顏色值取反,得到輸出圖像 res
。
四、主函數(shù)實現(xiàn)
int main() { cv::Mat img = cv::imread("E:/pro/sdl_code/res/test_img.png"); if (img.empty()) { std::cerr << "Error: Image not found." << std::endl; return -1; } cv::Mat sine_wave_img, cosine_wave_img, triangle_wave_img, sawtooth_wave_img, scale_img, rotate_img, gray_img, edge_img, blur_img, sharp_img, invert_img; // 不同波形效果 wave(img, sine_wave_img, "sine", 20, 0.1); // 正弦波 wave(img, cosine_wave_img, "cosine", 20, 0.1); // 余弦波 wave(img, triangle_wave_img, "triangle", 20, 0.1); // 三角波 wave(img, sawtooth_wave_img, "sawtooth", 20, 10); // 鋸齒波 // 縮放圖像 scale(img, scale_img, 0.5, 0.5); // 旋轉(zhuǎn)圖像 rotate1(img, rotate_img, 45); // 顏色變換(灰度圖) grayscale(img, gray_img); // 邊緣檢測 edge_detection(img, edge_img); // 高斯模糊 gaussian_blur(img, blur_img); // 圖像銳化 sharpen(img, sharp_img); // 顏色反轉(zhuǎn) invert_colors(img, invert_img); // 顯示所有效果 cv::imshow("Original Image", img); cv::imshow("Sine Wave Effect", sine_wave_img); cv::imshow("Cosine Wave Effect", cosine_wave_img); cv::imshow("Triangle Wave Effect", triangle_wave_img); cv::imshow("Sawtooth Wave Effect", sawtooth_wave_img); cv::imshow("Scaled Image", scale_img); cv::imshow("Rotated Image", rotate_img); cv::imshow("Grayscale Image", gray_img); cv::imshow("Edge Detection", edge_img); cv::imshow("Gaussian Blur", blur_img); cv::imshow("Sharpened Image", sharp_img); cv::imshow("Inverted Colors", invert_img); cv::waitKey(0); // 保存結(jié)果圖像 //cv::imwrite("output_wave_image.jpg", wave_img); //cv::imwrite("output_scaled_image.jpg", scale_img); //cv::imwrite("output_rotated_image.jpg", rotate_img); //cv::imwrite("output_grayscale_image.jpg", gray_img); //cv::imwrite("output_edge_detection.jpg", edge_img); //cv::imwrite("output_gaussian_blur.jpg", blur_img); //cv::imwrite("output_sharpened_image.jpg", sharp_img); //cv::imwrite("output_inverted_colors.jpg", invert_img); return 0; }
主函數(shù)首先讀取輸入圖像,如果圖像讀取失敗,則輸出錯誤信息并返回 -1。然后,創(chuàng)建多個輸出圖像用于存儲不同的處理效果。接下來,分別調(diào)用不同的函數(shù)對輸入圖像進行處理,得到各種效果的輸出圖像。最后,顯示所有的圖像,并等待用戶按下任意鍵退出程序。如果需要保存結(jié)果圖像,可以取消注釋相應(yīng)的代碼行。
五、總結(jié)
本文介紹了如何使用 OpenCV 實現(xiàn)多種圖像變換和處理效果,包括重映射圖像創(chuàng)建波形效果、縮放圖像、旋轉(zhuǎn)圖像、顏色變換、邊緣檢測、高斯模糊、圖像銳化和顏色反轉(zhuǎn)等。通過這些功能,我們可以對圖像進行各種操作,從而實現(xiàn)不同的視覺效果。在實際應(yīng)用中,可以根據(jù)具體需求選擇合適的圖像變換和處理方法,以達到更好的效果。
希望本文對大家學(xué)習(xí)和使用 OpenCV 有所幫助。如果有任何問題或建議,歡迎在評論區(qū)留言。首先介紹了 OpenCV 的重要性和本文要展示的內(nèi)容。接著進行環(huán)境準(zhǔn)備的說明,包括安裝 OpenCV 和 C++編譯器。然后對關(guān)鍵代碼進行詳細分析,分別解釋了定義常量 M_PI
、各種圖像變換和處理函數(shù)的作用及實現(xiàn)原理。最后展示了主函數(shù)的實現(xiàn),包括讀取圖像、創(chuàng)建輸出圖像、調(diào)用各種處理函數(shù)、顯示圖像和等待用戶操作等。整體文章結(jié)構(gòu)清晰,按照介紹、準(zhǔn)備、分析、實現(xiàn)和總結(jié)的順序進行撰寫,以幫助讀者更好地理解 OpenCV 的圖像變換和處理功能。
到此這篇關(guān)于OpenCV圖像變換與處理實戰(zhàn)方法的文章就介紹到這了,更多相關(guān)OpenCV圖像變換與處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
visual studio 2019工具里添加開發(fā)中命令提示符的方法
這篇文章主要介紹了visual studio 2019工具里添加開發(fā)中命令提示符的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03C語言容易被忽視的函數(shù)設(shè)計原則基礎(chǔ)
C語言的設(shè)計目標(biāo)是提供一種能以簡易的方式編譯、處理低級存儲器、產(chǎn)生少量的機器碼以及不需要任何運行環(huán)境支持便能運行的編程語言.那么C語言函數(shù)設(shè)計的一般原則和技巧都是怎樣的呢,下面帶你了解2022-04-04