برای اینکار می بایستی تصویر cv::Mat را به فرمت image کتابخانه Qt تبدیل کنید و سپس متن را با استفاده از متد drawText از کلاس QPainter بر روی image نوشته و در انتها QImage را به cv::Mat تبدیل کنید.
QImage mat2Image(const cv::Mat &mat, MatColorOrder order, QImage::Format formatHint)
{
Q_ASSERT(mat.channels()==1 || mat.channels()==3 || mat.channels()==4);
Q_ASSERT(mat.depth()==CV_8U || mat.depth()==CV_16U || mat.depth()==CV_32F);
if (mat.empty())
return QImage();
//Adjust mat channels if needed, and find proper QImage format.
QImage::Format format;
cv::Mat mat_adjustCn;
if (mat.channels() == 1) {
format = formatHint;
if (formatHint != QImage::Format_Indexed8
#if QT_VERSION >= 0x050500
&& formatHint != QImage::Format_Alpha8
&& formatHint != QImage::Format_Grayscale8
#endif
) {
format = QImage::Format_Indexed8;
}
} else if (mat.channels() == 3) {
#if QT_VERSION >= 0x040400
format = QImage::Format_RGB888;
if (order == MCO_BGR)
cv::cvtColor(mat, mat_adjustCn, CV_BGR2RGB);
#else
format = QImage::Format_RGB32;
cv::Mat mat_tmp;
cv::cvtColor(mat, mat_tmp, order == MCO_BGR ? CV_BGR2BGRA : CV_RGB2BGRA);
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
mat_adjustCn = mat_tmp;
#else
mat_adjustCn = argb2bgra(mat_tmp);
#endif
#endif
} else if (mat.channels() == 4) {
//Find best format if the formatHint can not be applied.
format = findClosestFormat(formatHint);
if (format != QImage::Format_RGB32
&& format != QImage::Format_ARGB32
&& format != QImage::Format_ARGB32_Premultiplied
#if QT_VERSION >= 0x050200
&& format != QImage::Format_RGBX8888
&& format != QImage::Format_RGBA8888
&& format != QImage::Format_RGBA8888_Premultiplied
#endif
) {
#if QT_VERSION >= 0x050200
format = order == MCO_RGBA ? QImage::Format_RGBA8888 : QImage::Format_ARGB32;
#else
format = QImage::Format_ARGB32;
#endif
}
//Channel order requried by the target QImage
MatColorOrder requiredOrder = getColorOrderOfRGB32Format();
#if QT_VERSION >= 0x050200
if (formatHint == QImage::Format_RGBX8888
|| formatHint == QImage::Format_RGBA8888
|| formatHint == QImage::Format_RGBA8888_Premultiplied) {
requiredOrder = MCO_RGBA;
}
#endif
if (order != requiredOrder)
mat_adjustCn = adjustChannelsOrder(mat, order, requiredOrder);
}
if (mat_adjustCn.empty())
mat_adjustCn = mat;
//Adjust mat depth if needed.
cv::Mat mat_adjustDepth = mat_adjustCn;
if (mat.depth() != CV_8U)
mat_adjustCn.convertTo(mat_adjustDepth, CV_8UC(mat_adjustCn.channels()), mat.depth() == CV_16U ? 1/255.0 : 255.0);
//Should we convert the image to the format specified by formatHint?
QImage image = mat2Image_shared(mat_adjustDepth, format);
if (format == formatHint || formatHint == QImage::Format_Invalid)
return image.copy();
else
return image.convertToFormat(formatHint);
}
cv::Mat image2Mat(const QImage &img, int requiredMatType, MatColorOrder requriedOrder)
{
int targetDepth = CV_MAT_DEPTH(requiredMatType);
int targetChannels = CV_MAT_CN(requiredMatType);
Q_ASSERT(targetChannels==CV_CN_MAX || targetChannels==1 || targetChannels==3 || targetChannels==4);
Q_ASSERT(targetDepth==CV_8U || targetDepth==CV_16U || targetDepth==CV_32F);
if (img.isNull())
return cv::Mat();
//Find the closest image format that can be used in image2Mat_shared()
QImage::Format format = findClosestFormat(img.format());
QImage image = (format==img.format()) ? img : img.convertToFormat(format);
MatColorOrder srcOrder;
cv::Mat mat0 = image2Mat_shared(image, &srcOrder);
//Adjust mat channells if needed.
cv::Mat mat_adjustCn;
const float maxAlpha = targetDepth==CV_8U ? 255 : (targetDepth==CV_16U ? 65535 : 1.0);
if (targetChannels == CV_CN_MAX)
targetChannels = mat0.channels();
switch(targetChannels) {
case 1:
if (mat0.channels() == 3) {
cv::cvtColor(mat0, mat_adjustCn, CV_RGB2GRAY);
} else if (mat0.channels() == 4) {
if (srcOrder == MCO_BGRA)
cv::cvtColor(mat0, mat_adjustCn, CV_BGRA2GRAY);
else if (srcOrder == MCO_RGBA)
cv::cvtColor(mat0, mat_adjustCn, CV_RGBA2GRAY);
else//MCO_ARGB
cv::cvtColor(argb2bgra(mat0), mat_adjustCn, CV_BGRA2GRAY);
}
break;
case 3:
if (mat0.channels() == 1) {
cv::cvtColor(mat0, mat_adjustCn, requriedOrder == MCO_BGR ? CV_GRAY2BGR : CV_GRAY2RGB);
} else if (mat0.channels() == 3) {
if (requriedOrder != srcOrder)
cv::cvtColor(mat0, mat_adjustCn, CV_RGB2BGR);
} else if (mat0.channels() == 4) {
if (srcOrder == MCO_ARGB) {
mat_adjustCn = cv::Mat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 3));
int ARGB2RGB[] = {1,0, 2,1, 3,2};
int ARGB2BGR[] = {1,2, 2,1, 3,0};
cv::mixChannels(&mat0, 1, &mat_adjustCn, 1, requriedOrder == MCO_BGR ? ARGB2BGR : ARGB2RGB, 3);
} else if (srcOrder == MCO_BGRA) {
cv::cvtColor(mat0, mat_adjustCn, requriedOrder == MCO_BGR ? CV_BGRA2BGR : CV_BGRA2RGB);
} else {//RGBA
cv::cvtColor(mat0, mat_adjustCn, requriedOrder == MCO_BGR ? CV_RGBA2BGR : CV_RGBA2RGB);
}
}
break;
case 4:
if (mat0.channels() == 1) {
if (requriedOrder == MCO_ARGB) {
cv::Mat alphaMat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 1), cv::Scalar(maxAlpha));
mat_adjustCn = cv::Mat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 4));
cv::Mat in[] = {alphaMat, mat0};
int from_to[] = {0,0, 1,1, 1,2, 1,3};
cv::mixChannels(in, 2, &mat_adjustCn, 1, from_to, 4);
} else if (requriedOrder == MCO_RGBA) {
cv::cvtColor(mat0, mat_adjustCn, CV_GRAY2RGBA);
} else {//MCO_BGRA
cv::cvtColor(mat0, mat_adjustCn, CV_GRAY2BGRA);
}
} else if (mat0.channels() == 3) {
if (requriedOrder == MCO_ARGB) {
cv::Mat alphaMat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 1), cv::Scalar(maxAlpha));
mat_adjustCn = cv::Mat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 4));
cv::Mat in[] = {alphaMat, mat0};
int from_to[] = {0,0, 1,1, 2,2, 3,3};
cv::mixChannels(in, 2, &mat_adjustCn, 1, from_to, 4);
} else if (requriedOrder == MCO_RGBA) {
cv::cvtColor(mat0, mat_adjustCn, CV_RGB2RGBA);
} else {//MCO_BGRA
cv::cvtColor(mat0, mat_adjustCn, CV_RGB2BGRA);
}
} else if (mat0.channels() == 4) {
if (srcOrder != requriedOrder)
mat_adjustCn = adjustChannelsOrder(mat0, srcOrder, requriedOrder);
}
break;
default:
break;
}
//Adjust depth if needed.
if (targetDepth == CV_8U)
return mat_adjustCn.empty() ? mat0.clone() : mat_adjustCn;
if (mat_adjustCn.empty())
mat_adjustCn = mat0;
cv::Mat mat_adjustDepth;
mat_adjustCn.convertTo(mat_adjustDepth, CV_MAKE_TYPE(targetDepth, mat_adjustCn.channels()), targetDepth == CV_16U ? 255.0 : 1/255.0);
return mat_adjustDepth;
}
void drawUnicode(cv::Mat & img, const std::wstring& str, const cv::Rect& region, const cv::Scalar& color,
const std::string& font_name, int font_size)
{
QPixmap pix;
QImage image = mat2Image(img);
QPainter p(&image);
p.setPen(QPen(QColor(color.val[2], color.val[1], color.val[0])));
QString fnt_name = QString::fromStdString(font_name);
QFont font = p.font();
font.setPointSize(font_size);
font.setFamily(fnt_name);
p.setFont(font);
float factor = (float)region.width / p.fontMetrics().width(QString::fromStdWString(str));
//if ((factor < 1) || (factor > 1.25))
//{
// QFont f = p.font();
// f.setPointSizeF(f.pointSizeF()*factor);
// p.setFont(f);
//}
p.drawText(rect2QRectF(region), Qt::AlignCenter, QString::fromStdWString(str));
img = image2Mat(image);
}