opencv imread() on Windows for non-ASCII file names

匿名 (未验证) 提交于 2019-12-03 01:17:01

问题:

We have an OpenCV problem of opening (and writing) file paths that contain non-Ascii characters on Windows. I saw questions OpenCV imread with foreign characters and imread(openCV),QString unicodes but still didn't understand a proper way of solving the problem.

As far I as I saw in the OpenCV source code, it uses fopen even on Windows (instead of _wfopen) and afaik fopen does not handle non-ascii characters on Windows. From the questions above I saw that there could be some trick using QStrings, but if it works what does it exactly do? How does it transform a unicode string to a character array that will be accepted by Windows' fopen()?

P.S. We don't use QT

Thanks in advance!

回答1:

The way to do this without hacking the OpenCV source code is to use _wfopen (as Remy suggested) to read the whole file into a memory buffer. Then use OpenCV's function imdecode to create a cv::Mat from that buffer.

You can do the reverse too, if necessary - i.e. use imencode to write an image to a memory buffer, then use _wfopen to open a file with a UNICODE name and write the buffer to it (alternatively, you could just imwrite to a temporary file and then move/rename it using the appropriate API function).



回答2:

Microsoft's version of fopen() in Visual Studio supports a non-standard css mode flag for enabling reading/writing of Unicode data, but it does not support Unicode filenames. You have to use _wfopen() for that, so you will have to tweak OpenCV's source code so you can pass in a Unicode filename and open it with _wfopen() instead of fopen().



回答3:

Here my solution using std::ifstream:

std::ifstream file(path.toStdWString(), std::iostream::binary); if (!file.good()) {     return cv::Mat(); } file.exceptions(std::ifstream::badbit | std::ifstream::failbit | std::ifstream::eofbit); file.seekg(0, std::ios::end); std::streampos length(file.tellg()); std::vector buffer(static_cast<:size_t>(length)); if (static_cast<:size_t>(length) == 0) {     return cv::Mat(); } file.seekg(0, std::ios::beg); try {     file.read(buffer.data(), static_cast<:size_t>(length)); } catch (...) {     return cv::Mat(); } file.close(); cv::Mat image = cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR); return image; 

Or a bit shorter using Qt:

QFile file(path); std::vector buffer; buffer.resize(file.size()); if (!file.open(QIODevice::ReadOnly)) {     return cv::Mat(); } file.read(buffer.data(), file.size()); file.close(); cv::Mat image = cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR); return image; 


回答4:

Try this:

cv::Mat ReadImage(const wchar_t* filename) {     FILE* fp = _wfopen(filename, L"rb");     if (!fp)     {         return Mat::zeros(1, 1, CV_8U);     }     fseek(fp, 0, SEEK_END);     long sz = ftell(fp);     char* buf = new char[sz];     fseek(fp, 0, SEEK_SET);     long n = fread(buf, 1, sz, fp);     _InputArray arr(buf, sz);     Mat img = imdecode(arr, CV_LOAD_IMAGE_COLOR);     delete[] buf;     fclose(fp);     return img; } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!