0

I have to transform QImage to cv::Mat, if I use technique described in similar topics, I receive different numbers of contours (7--8) and strange result matrix, but if I do

QImage im;
im.save ("tmp.bmp");
cv::Mat rImage;
rImage = cv::imread ("tmp.bmp", CV_LOAD_IMAGE_GRAYSCALE);

function findContours works fine and properly. What is the difference between these techniques and which way I can archive equal results between these approaches ?

Community
  • 1
  • 1
Yuriy Rusinov
  • 61
  • 2
  • 5
  • It probably depends on the QImage format. What's yours? – Miki Nov 25 '16 at 12:59
  • Source image in RGB32 format. – Yuriy Rusinov Nov 25 '16 at 13:04
  • Can you show which code you're actually using, and what's the strange result you get? – Miki Nov 25 '16 at 13:07
  • cv::Mat qimage_to_mat_cpy(const QImage &img, int format) { uchar* b = const_cast (img.bits ()); int c = img.bytesPerLine(); cv::Mat mat = cv::Mat(img.height(), img.width(), format, b, c).clone(); return mat; } – Yuriy Rusinov Nov 25 '16 at 13:09
  • please try using [this](https://asmaloney.com/2013/11/code/converting-between-cvmat-and-qimage-or-qpixmap/) code. The `QImageToCvMat` function... that should work for your case (there are a few things to correct/update in general). – Miki Nov 25 '16 at 13:10

2 Answers2

0

Your code works for me.

int main(int argc, char *argv[]){
    QImage img(QString("lena.bmp"));
    QImage img2 = img.convertToFormat(QImage::Format_RGB32);
    cv::Mat imageMat = qimage_to_cvmat_copy(img2, CV_8UC4);
    cv::namedWindow("lena");
    cv::imshow("lena", imageMat);
    cv::waitKey(0);
}
cv::Mat qimage_to_cvmat_copy(const QImage &img, int format)
{
    uchar* b = const_cast<uchar*> (img.bits ());
    int c = img.bytesPerLine();
    return cv::Mat(img.height(), img.width(), format, b, c).clone();
}

Make sure your Mat format is CV_8UC4 if your QImage format is Format_RGB32. You don't have to do a cvtColor or mixChannels.

Yancey
  • 151
  • 4
  • OK, I do it, but findContours function gives an exception OpenCV Error: Unsupported format or combination of formats ([Start]FindContours support only 8uC1 and 32sC1 images) in cvStartFindContours, – Yuriy Rusinov Nov 26 '16 at 21:57
  • findContours only work with 8-bit single channel image or 32SC1 image. See [link](http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours#findcontours). You need to convert the 4 channel mat image to a single channel image first. This usually can be done by cvtColor with code CV_RGBA2GRAY – Yancey Nov 28 '16 at 16:52
  • Sorry, but one's more question CV_RGBA2GRAY or CV_RGB2GRAY ? I find CV_RGB2GRAY only in documentation on 2.3 and 2.4 versions – Yuriy Rusinov Nov 30 '16 at 12:07
  • In opencv 3.1 it is cv::COLOR_RGBA2GRAY and cv::COLOR_RGB2GRAY. Also, your input mat has to be a binary image for findContours to work. It depends on your project how you want to achieve that. Normally it can be done by converting the RGBA image to a grayscale image and then thresholding the grayscale image using cv::threshold(). – Yancey Nov 30 '16 at 15:18
0

All !

As mentioned above I used conversion QImage to cv::Mat as described here. My source code became something like this

QImage srcIm (argv[1]);
QImage img2 = srcIm.convertToFormat(QImage::Format_ARGB32);
Mat src_gray = QImageToCvMat (img2);
cvtColor (src_gray, src_gray1, CV_RGB2GRAY);

Mat bwimg = src_gray1.clone();// > 127;
vector<vector<Point> > contours;

findContours( bwimg, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE );    

All works fine.

Yuriy Rusinov
  • 61
  • 2
  • 5