I am trying to load an image with unicode characters in its path.
cv::imread
doesn't take a std::wstring
as input, so I tried to convert the wide string to a common string first:
#pragma warning(push)
#pragma warning(disable: 4996)
// See https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string
inline std::string wsstring_2_string(const std::wstring& wstr)
{
using convert_typeX = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_typeX, wchar_t> converterX;
return converterX.to_bytes(wstr);
}
#pragma warning(pop)
Then I load the image:
const std::wstring imageWidePath = L"D:\\沙发模型12_0017.jpg";
const std::string imagePath = wsstring_2_string(imageWidePath);
const cv::Mat image = cv::imread(imagePath, cv::IMREAD_UNCHANGED);
assert(image.cols > 0 && image.rows > 0);
wsstring_2_string()
returns D:\æ²™å‘æ¨¡åž‹12_0017.jpg
, then cv::imread
fails, which is legit.
I checked this answer. Basically, a solution is to first read the file as a byte array using an OS function that takes a wide string as input. Then build an input array (cv::InputArray
in C++) that is later fed to cv::imdecode
. But, how to build that InputArray
in C++?
Or, maybe there is another way to support Unicode?
Note that the image format is not know in advance. For example, it can be CV_32FC4 as well as CV_8UC3.
wsstring_2_string()
is returning a UTF-8 encoded std::string
, but cv::imread()
does not support UTF-8, which is why it fails.
You don't need to use cv::InputArray
directly. You can use any container that is convertible to InputArray
, such includes cv::Mat
, std::vector
, etc.
For example:
#include <fstream>
#include <vector>
#include <filesystem>
std::vector<char> readFileBytes(const std::wstring &filePath)
{
std::filesystem::path fsPath(filePath);
std::ifstream inFile(fsPath, std::ios::binary);
inFile.seekg(0, std::ios::end);
auto const fileSize = inFile.tellg();
inFile.seekg(0, std::ios::beg);
std::vector<char> bytes(fileSize);
inFile.read(reinterpret_cast<char*>(&bytes[0]), fileSize);
bytes.resize(inFile.tellg());
return bytes;
}
...
const std::wstring imageWidePath = L"D:\\沙发模型12_0017.jpg";
std::vector<char> bytes = readFileBytes(imageWidePath);
const cv::Mat image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
assert(image.cols > 0 && image.rows > 0);