I need reading image files with Unicode names however openCV function imread's argument for image names supports only strings. how can I save my Unicode path to string objects. Is there any solution for this?
Asked
Active
Viewed 2,589 times
6
-
There may be a proper solution, but as a workaround you could create symbolic links with pure ASCII filenames pointing to their Unicode filenames outside of OpenCV and let OpenCV just deal with them whilst indexing outside at the OS level. That is `ln -s UnicodeName.jpg ASCIIName.jpg` and then process `ASCIIName.jpg` with your program. – Mark Setchell Apr 12 '17 at 08:01
1 Answers
9
You can:
- open the file with
ifstream
, - read it all in a
std::vector<uchar>
, - decode it with
cv::imdecode
.
See the example below that loads into img2
an image with a Unicode filename using ifstream
:
#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;
}
If you're using Qt, you can do this a little more conveniently with QFile
and QString
, since QString
natively handle Unicode characters, and QFile
provides an easy way to the the file size:
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);
For completeness, here you can see how to do this in Python

Miki
- 40,887
- 13
- 123
- 202
-
1
-
If the image has rotation, the rotation is lost with this in my tries. Imread result is diffent for those images. – Koray Aug 10 '18 at 13:59
-
@Koray _"if the image has rotation"_ what do you mean? in the exif metadata maybe? If so, `imread` ignores about exif metadata. In any case this is not related to having the name with unicode chars – Miki Aug 10 '18 at 14:03
-
@Miki I mean orientation. Defined in Image PropertyIdList -> 274 I have tested your code and it works just fine with the images that has no orientation. However the result differs from Imread when a rotation has been set to the image. (I mean the the fist code, that uses ifstream) – Koray Aug 10 '18 at 16:55
-
@kor That is the orientation stored in the exif metadata and, as already mentioned, opencv ignores it. So there is no way to load a "rotated" image correctly with opencv. As such, it's not related to the unicode filename nor to this question. In the past I used exiv2 library to read the metadata and rotate /mirror the image loaded by opencv accordingly – Miki Aug 10 '18 at 18:34
-
@Miki ok. I'm not saying that your code does not solve what is being asked in the question. And I don't have a deep knowledge on what OpenCV does with Imread. All I say is: "I have tested it, and the results are different when there is an orientation in the image." Maybe I'm testing with a diffent version of OpenCV, I dont know, but I had no problems when I use Imread.(Not concerning unicode of course) – Koray Aug 10 '18 at 18:43
-
-
If I understand correctly it's very weird, since imread internally uses imdecode, so the final result should be equivalent. Sorry but I'm on holiday and can't look into this further. You can of course ask a new question on SO – Miki Aug 10 '18 at 18:52
-
@kor oh good to know, I didn't know about that. It seems also that in some versions exif parsing was implemented only in imread, and not in imdecode (and probably the imread implementation changed a lot from the last time I red it) . That could probably be your case. Try to use that latest opencv version and see what happens ;) – Miki Aug 27 '18 at 22:12
-
Thanks very much for your solution. DO we need to delete any pointer or close any thing to prevent from memory leak. – hjyanghj Jan 11 '19 at 03:44
-
@hjyanghj it should be fine as it is. You can put all the file-related code in a block, so when it goes out of scope it closes the file and frees the stream automatically – Miki Jan 11 '19 at 09:37