如何在C++中读取路径含Unicode字符的图片?
如何在C++中读取路径含Unicode字符的图片?
我太懂这种踩坑的感觉了——OpenCV自带的cv::imread偏偏不支持std::wstring类型的路径,直接转成普通字符串又经常因为编码乱码读不出图片,尤其是路径里有Unicode字符的时候,简直头大!别慌,给你几个亲测好用的解决办法:
方法1:二进制读取+解码(跨平台首选)
这个方法完全绕开cv::imread的编码短板,直接用宽字符路径读取文件的二进制内容,再让OpenCV解码成Mat,不管路径里有什么Unicode字符都能稳稳识别,而且Windows、Linux、macOS都能用。
代码示例:
#include <opencv2/opencv.hpp> #include <fstream> #include <vector> cv::Mat imread_unicode(const std::wstring& path) { // 以二进制模式打开文件 std::ifstream file(path, std::ios::binary | std::ios::ate); if (!file.is_open()) { // 打开失败返回空Mat return cv::Mat(); } // 获取文件大小 std::streamsize file_size = file.tellg(); file.seekg(0, std::ios::beg); // 读取文件内容到缓冲区 std::vector<char> buffer(file_size); if (file.read(buffer.data(), file_size)) { // 解码缓冲区内容为图片Mat return cv::imdecode(cv::Mat(buffer), cv::IMREAD_COLOR); } // 读取失败返回空Mat return cv::Mat(); } // 调用方式 int main() { cv::Mat img = imread_unicode(L"C:/测试图片/中文路径.jpg"); if (!img.empty()) { cv::imshow("Unicode路径图片", img); cv::waitKey(0); } return 0; }
方法2:宽字符转UTF-8字符串(Windows专属)
如果你非要用cv::imread原生接口,那得把宽字符路径转成UTF-8编码的普通字符串,Windows下可以用系统API来完成转换,转完再传给cv::imread就能正常识别了。
代码示例:
#include <windows.h> #include <opencv2/opencv.hpp> #include <string> // 把宽字符串转成UTF-8编码的普通字符串 std::string wstring_to_utf8(const std::wstring& wstr) { if (wstr.empty()) return ""; // 计算需要的缓冲区大小 int buffer_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); std::string utf8_str(buffer_size, 0); // 执行转换 WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &utf8_str[0], buffer_size, NULL, NULL); return utf8_str; } // 调用方式 int main() { std::wstring unicode_path = L"C:/测试图片/中文路径.jpg"; cv::Mat img = cv::imread(wstring_to_utf8(unicode_path), cv::IMREAD_COLOR); if (!img.empty()) { cv::imshow("Unicode路径图片", img); cv::waitKey(0); } return 0; }
注意:这个方法依赖Windows的WideCharToMultiByte函数,只能在Windows系统用,跨平台场景不推荐。
方法3:FileStorage读取(偏门思路,不推荐)
这个算是拓展知识,用OpenCV的cv::FileStorage接口读取,但它只适合读取存成XML/YAML格式的图片,普通的JPG、PNG用这个太麻烦,所以只做个简单介绍:
#include <opencv2/opencv.hpp> int main() { std::wstring unicode_path = L"C:/测试图片/存储为XML的图片.xml"; cv::FileStorage fs(unicode_path, cv::FileStorage::READ | cv::FileStorage::FORMAT_XML); cv::Mat img; fs["image"] >> img; fs.release(); if (!img.empty()) { cv::imshow("XML存储的图片", img); cv::waitKey(0); } return 0; }
内容来源于stack exchange
相关产品推荐
相关产品推荐

