圖像處理一直是計算機視覺中的一個重要領域,opencv作為開源的計算機視覺庫,實現了很多經典的圖像處理算法。其中,cv::imdecode函數是非常重要的一個函數,它能夠將存儲在內存中的圖像解碼成opencv的Mat數據類型。這篇文章將從不同的角度對這個函數進行詳細的講解。
一、使用cv::imdecode函數讀取圖片文件
cv::imdecode函數最常見的用法是讀取圖片文件。它可以將圖片文件讀取到內存中,並將其解碼為opencv的Mat格式。
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include #include using namespace std; using namespace cv; int main() { string img_path = "test.png"; vector<uchar> img_data; Mat img; // 讀取圖片文件到內存中 ifstream in(img_path, std::ios::binary); in.unsetf(std::ios::skipws); // 不跳過空白字符 streampos file_size; in.seekg(0, ios::end); file_size = in.tellg(); in.seekg(0, ios::beg); img_data.reserve(file_size); img_data.insert(img_data.begin(), istream_iterator<uchar>(in), istream_iterator<uchar>()); in.close(); // 解碼圖片並顯示 img = imdecode(img_data, CV_LOAD_IMAGE_COLOR); imshow("Image", img); waitKey(0); return 0; }
上述代碼中,我們首先讀取了一張圖片文件到內存中,然後將其解碼為opencv的Mat格式,並使用imshow函數顯示圖片。這是最常見的使用cv::imdecode函數的方式,它對於讀取網絡上的圖片等場景非常方便。
二、使用cv::imdecode函數解碼編碼過的圖像
有一些場景下,圖像在傳輸過程中可能會進行編碼。比如,JPEG圖像和PNG圖像就是經過編碼的。在這種情況下,我們可以使用cv::imdecode函數將編碼後的圖像解碼為opencv的Mat格式。
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include #include using namespace std; using namespace cv; int main() { string img_path = "test.jpg"; vector<uchar> img_data; Mat img1, img2; // 讀取JPEG圖片文件到內存中 ifstream in(img_path, std::ios::binary); in.unsetf(std::ios::skipws); // 不跳過空白字符 streampos file_size; in.seekg(0, ios::end); file_size = in.tellg(); in.seekg(0, ios::beg); img_data.reserve(file_size); img_data.insert(img_data.begin(), istream_iterator<uchar>(in), istream_iterator<uchar>()); in.close(); // 解碼JPEG圖片並顯示 img1 = imdecode(img_data, CV_LOAD_IMAGE_COLOR); imshow("JPEG Image", img1); // 編碼圖像 vector<int> params; // JPEG參數 params.push_back(CV_IMWRITE_JPEG_QUALITY); // JPEG質量 params.push_back(60); // 圖片質量,0~100 imencode(".jpg", img1, img_data, params); // 解碼編碼後的JPEG圖片並顯示 img2 = imdecode(img_data, CV_LOAD_IMAGE_COLOR); imshow("Encoded and Decoded JPEG Image", img2); waitKey(0); return 0; }
上述代碼中,我們首先讀取了一張JPEG圖片文件到內存中,然後將其解碼為opencv的Mat格式並顯示。接着,我們將圖片編碼為JPEG格式,將編碼後的圖片重新解碼為opencv的Mat格式並顯示。這種方式可以用於測試編碼和解碼算法。注意,這裡需要將編碼後的數據存儲到vector<uchar>類型中,因為它是不定長的。
三、使用cv::imdecode函數解碼從網絡收到的圖像
在一些應用場景下,我們需要從網絡中接收圖像,然後進行處理。這時,cv::imdecode函數也能夠非常方便地解碼從網絡收到的圖像。
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include #include #include #pragma comment(lib, "ws2_32.lib") using namespace std; using namespace cv; int main() { string server_ip = "127.0.0.1"; int server_port = 8080; WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(server_ip.c_str()); server_addr.sin_port = htons(server_port); connect(sock, (sockaddr*)&server_addr, sizeof(server_addr)); // 接收圖像數據並解碼成opencv的Mat格式 vector<uchar> img_data; int img_size; recv(sock, (char*)&img_size, sizeof(img_size), 0); img_size = ntohl(img_size); img_data.resize(img_size); recv(sock, (char*)&img_data[0], img_size, 0); Mat img = imdecode(img_data, CV_LOAD_IMAGE_COLOR); imshow("Image", img); waitKey(0); closesocket(sock); WSACleanup(); return 0; }
上述代碼中,我們首先通過socket從服務器接收一個圖像數據包。接着,將數據包的長度和內容存儲到img_size和img_data中,並使用cv::imdecode函數將其解碼成opencv的Mat格式,最後使用imshow函數顯示圖片。
四、使用cv::imdecode函數解碼指定格式圖片
除了讀取文件和解碼編碼過的圖像以外,cv::imdecode函數還能夠解碼指定格式的圖片。比如,如果我們要讀取一張20通道的圖像,就可以使用cv::imdecode函數解碼。這種情況下,我們需要先將圖像編碼成一種通用格式,比如JPEG或PNG。
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include #include #include using namespace std; using namespace cv; int main() { string img_path = "test.tif"; vector<uchar> img_data; Mat img1, img2; // 讀取20通道的圖像文件到內存中 ifstream in(img_path, std::ios::binary); in.unsetf(std::ios::skipws); // 不跳過空白字符 streampos file_size; in.seekg(0, ios::end); file_size = in.tellg(); in.seekg(0, ios::beg); img_data.reserve(file_size); img_data.insert(img_data.begin(), istream_iterator<uchar>(in), istream_iterator<uchar>()); in.close(); // 將20通道的圖像編碼為PNG格式 vector<int> params; // PNG參數 params.push_back(CV_IMWRITE_PNG_COMPRESSION); // PNG壓縮程度 params.push_back(3); // 壓縮程度,0~9 imencode(".png", Mat(100, 100, CV_8UC(20), Scalar(0)), img_data, params); // 解碼PNG格式的圖像並顯示 img1 = imdecode(img_data, CV_LOAD_IMAGE_UNCHANGED); imshow("20-channel Image", img1); // 將20通道的圖像編碼為JPEG格式 params.clear(); // 清空參數 params.push_back(CV_IMWRITE_JPEG_QUALITY); // JPEG質量 params.push_back(60); // 圖片質量,0~100 imencode(".jpg", Mat(100, 100, CV_8UC(20), Scalar(0)), img_data, params); // 解碼JPEG格式的圖像並顯示 img2 = imdecode(img_data, CV_LOAD_IMAGE_UNCHANGED); imshow("20-channel Image Encoded and Decoded", img2); waitKey(0); return 0; }
上述代碼中,我們首先讀取了一張20通道的圖像文件到內存中。接着,我們將圖像編碼為PNG格式,並使用cv::imdecode函數將其解碼為opencv的Mat格式。同樣地,我們將圖像編碼為JPEG格式,並使用cv::imdecode函數將其解碼為opencv的Mat格式。這種方式可以用於特殊的圖像格式處理。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/188676.html