使用 imread 打开具有 unicode 名称的图像文件

Posted

技术标签:

【中文标题】使用 imread 打开具有 unicode 名称的图像文件【英文标题】:open image files with unicode names using imread 【发布时间】:2017-04-12 04:50:56 【问题描述】:

我需要读取带有 Unicode 名称的图像文件,但是 openCV 函数 imread 的图像名称参数仅支持字符串。如何将我的 Unicode 路径保存到字符串对象。有什么解决办法吗?

【问题讨论】:

可能有一个合适的解决方案,但作为一种解决方法,您可以使用指向 OpenCV 外部的 Unicode 文件名的纯 ASCII 文件名创建符号链接,并让 OpenCV 处理它们,同时在操作系统级别外部进行索引.那就是ln -s UnicodeName.jpg ASCIIName.jpg,然后用你的程序处理ASCIIName.jpg 【参考方案1】:

你可以:

    ifstream打开文件, 在std::vector<uchar> 中阅读所有内容, 使用cv::imdecode对其进行解码。

请参阅下面的示例,该示例使用ifstream 将具有Unicode 文件名的图像加载到img2

#include <opencv2\opencv.hpp>
#include <vector>
#include <fstream>

using namespace cv;
using namespace std;

int main()

    // This doesn't work with Unicode characters

    Mat img = imread("D:\\SO\\img\\æbärnɃ.jpg");
    if (img.empty()) 
        cout << "Doesn't work with Unicode filenames\n";
    
    else 
        cout << "Work with Unicode filenames\n";
        imshow("Unicode with imread", img);
    

    // This WORKS with Unicode characters

    // This is a wide string!!!
    wstring name = L"D:\\SO\\img\\æbärnɃ.jpg";

    // Open the file with Unicode name
    ifstream f(name, iostream::binary);

    // Get its size
    filebuf* pbuf = f.rdbuf();
    size_t size = pbuf->pubseekoff(0, f.end, f.in);
    pbuf->pubseekpos(0, f.in);

    // Put it in a vector
    vector<uchar> buffer(size);
    pbuf->sgetn((char*)buffer.data(), size);

    // Decode the vector
    Mat img2 = imdecode(buffer, IMREAD_COLOR);

    if (img2.empty()) 
        cout << "Doesn't work with Unicode filenames\n";
    
    else 
        cout << "Work with Unicode filenames\n";
        imshow("Unicode with fstream", img2);
    

    waitKey();
    return 0;


如果您使用的是 Qt,则可以使用 QFileQString 更方便地执行此操作,因为 QString 本身可以处理 Unicode 字符,而 QFile 提供了一种简单的文件大小处理方法:

QString name = "path/to/unicode_img";
QFile file(name);
file.open(QFile::ReadOnly);
qint64 sz = file.size();
std::vector<uchar> buf(sz);
file.read((char*)buf.data(), sz);
cv::Mat3b img = cv::imdecode(buf, cv::IMREAD_COLOR);

为了完整起见,here 您可以查看如何在 Python 中执行此操作

【讨论】:

很酷的解决方案 - 天才! @ahmid 很高兴它有帮助 ;) 如果图像有旋转,在我的尝试中旋转会丢失。这些图像的读取结果不同。 @Koray "如果图像有旋转" 你是什么意思?也许在 exif 元数据中?如果是这样,imread 会忽略 exif 元数据。无论如何,这与使用 unicode 字符的名称无关 @Miki 我的意思是方向。在 Image PropertyIdList -> 274 中定义我已经测试了您的代码,它适用于没有方向的图像。但是,当为图像设置旋转时,结果与 Imread 不同。 (我的意思是第一个使用 ifstream 的代码)

以上是关于使用 imread 打开具有 unicode 名称的图像文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中递归查找具有 Unicode 名称的文件?

正则表达式和 unicode

为啥 cv2.imread() 不存储我的图像文件的名称?

如何在 VBA 中打开具有相似名称的文件?

如何将 ANSI 文本转换为 Unicode?

编码/解码有啥区别?