图像处理一直是计算机视觉中的一个重要领域,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格式。这种方式可以用于特殊的图像格式处理。