opencv putText中文乱码

https://mangoroom.cn/opencv/opencv-puttext-chinese-characters.html

https://stackoverflow.com/questions/45116828/opencv-cvaddtext-exception-if-no-window

opencv不支持渲染中文字符的原由
opencv不支持渲染中文字符的本质是不支持对utf-8的字符渲染,opencv库中的cv::putText()函数仅支持对ascii码,这是一个很小的字符编码,想要支持中文或者其他字符的渲染就需要支持Unicode的字符集。其实早期的opencv是字符Unicode的字符渲染的,在c语言版本时代采用的是FreeType库实现的,但由于FreeFype是GPL版权发布的库,和OpenCV版权并不一致,因此目前还没有合并到OpenCV

解决方法:

编译opencv的时候,勾选wiht Qt的选项,因为Qt的渲染是支持Unicode字符集的,所以在编译opencv的时候联合编译qt的部分代码可以实现对Unicode的支持。将qt添加到opencv里一起编译本是一件比较麻烦的事,所幸的是opencv官方已经替我们解决了,已经将此选项写在了cmake的构建文件里。所以在编译的时候只需要我们勾选即可。而且在qt的官网可以找到编译教程,教程地址:
https://wiki.qt.io/How_to_setup_Qt_and_openCV_on_Windows。

简单地说,参考教程,只需要在编译opencv的时候,勾选以下两个选项即可

WITH_QT
WITH_OPENGL

Mat img = imread("lena.jpg");
cv::addText(img, "中文测试", cv::Point(100, 50), cv::fontQt("Times"));
imwrite("res.bmp", img);

/home/vitaly/CLionProjects/opencvTest/cmake-build-debug/opencvTest /home/vitaly/Pictures/img.jpg OpenCV Error: Null pointer (NULL guiReceiver (please create a window)) in cvAddText, file /home/vitaly/Documents/opencv/opencv/modules/highgui/src/window_QT.cpp, line 114 terminate called after throwing an instance of 'cv::Exception' what(): /home/vitaly/Documents/opencv/opencv/modules/highgui/src/window_QT.cpp:114: error: (-27) NULL guiReceiver (please create a window) in function cvAddText

which goes away if I add

namedWindow("test", WINDOW_AUTOSIZE);

before addText.

However, I cannot understand why would qt or opencv need an opened window for that ? I don't need to display the image, I'm only using it to put text on image and then save it, I don't want to create any windows.

So here's my questions

  1. Why window is required for that ?
  2. Is there a way around it ? (To not create windows)

As you can see in the source code:

CV_IMPL void cvAddText(const CvArr* img, const char* text, CvPoint org, CvFont* font)
{
    if (!guiMainThread)
        CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );

    QMetaObject::invokeMethod(guiMainThread,
        "putText",
        autoBlockingConnection(),
        Q_ARG(void*, (void*) img),
        Q_ARG(QString,QString::fromUtf8(text)),
        Q_ARG(QPoint, QPoint(org.x,org.y)),
        Q_ARG(void*,(void*) font));
}

addText requires a gui thread. as the actual drawing happens in that thread. No thread, no function, no drawing...

Why is it like that? Well because it made sense to somebody I guess.

It's open source, feel free to code your own workaround. Otherwise use OpenCV's putText.

你可能感兴趣的:(Qt,opencv,qt)