圖像處理一直是計算機視覺中的一個重要領域,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-hant/n/188676.html
微信掃一掃
支付寶掃一掃