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

六月ゝ 毕业季﹏ 提交于 2019-11-27 03:20:54

问题


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:


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;
}



回答4:


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<char> buffer(static_cast<std::size_t>(length));
if (static_cast<std::size_t>(length) == 0) {
    return cv::Mat();
}
file.seekg(0, std::ios::beg);
try {
    file.read(buffer.data(), static_cast<std::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<char> 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;


来源:https://stackoverflow.com/questions/24769623/opencv-imread-on-windows-for-non-ascii-file-names

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