OpenCV【2】---读取png图片显示到QT label上的问题

问题一:

  操作图片test.png是一个365x365的PNG图片

OpenCV【2】---读取png图片显示到QT label上的问题_第1张图片

  通过OpenCV自带的GUI显示出来图像是没问题的,如下操作代码所示:

    QStringfileName=QFileDialog::getOpenFileName(this,
                tr("OpenImage"),".",
                tr("ImageFiles(*.png*.jpg*.jpeg*.bmp)"));
    if(fileName.length()<=0)return;
    //imread的第二个参数:读取4通道的png图像。其中第四个通道的数据类型和其他通道的一样,都是uchar型,完全透明为0,否则为255
    image=cv::imread(fileName.toUtf8().data());
    QString status = QString::number(image.rows)+"x"+QString::number(image.cols);
    ui->label_2->setText(status);
    //OpenCV显示出来
    cv::namedWindow("OriginalImage");
    cv::imshow("OriginalImage",image);    

OpenCV【2】---读取png图片显示到QT label上的问题_第2张图片

  但是经过下面的处理之后,图片显示不正常了:

    //改变色彩通道顺序,将Mat的BGR顺序反转为QImage中的RGB顺序
    cv::cvtColor(image,image,CV_BGR2RGB);
    //QT图像
    QImageimg=QImage((constunsignedchar*)(image.data),
    image.cols,image.rows,QImage::Format_RGB888);
    //显示在label中:voidsetPixmap(constQPixmap&);
    ui->label->setPixmap(QPixmap::fromImage(img));
    //改变label的尺寸已自适应图像
    ui->label->resize(ui->label->pixmap()->size());

OpenCV【2】---读取png图片显示到QT label上的问题_第3张图片

问题二:

OpenCV【2】---读取png图片显示到QT label上的问题_第4张图片

  操作图片test1.png是一个256x256的PNG图片(原图如上图),同样的代码,同样的操作,用OpenCV自带GUI显示如下:

OpenCV【2】---读取png图片显示到QT label上的问题_第5张图片

  而处理后用QT label显示如下:

OpenCV【2】---读取png图片显示到QT label上的问题_第6张图片

  正常!!!对比两个问题,到底哪里出现了问题呢?

  又重新试了几张不同大小的图片:200x200,356x356均没问题。分析可以知道cv::Mat 读取的图片是没有问题的,那肯定就是QImage这里出问题了。查了QImage的构造函数:

OpenCV【2】---读取png图片显示到QT label上的问题_第7张图片

   其中bytesPerLine参数为每一行的字节数。

    //改变色彩通道顺序,将Mat的BGR顺序反转为QImage中的RGB顺序
    cv::cvtColor(image,image,CV_BGR2RGB);
    //QT图像
    //QImage::Format_RGB888,像素为24位
    QImageimg;
    if(image.channels()==3){
        img=QImage((constunsignedchar*)(image.data),
        image.cols,image.rows,image.cols*image.channels(),QImage::Format_RGB888);
    }
    //QImage::Format_Indexed8,像素为8位
    else{
        img=QImage((constunsignedchar*)(image.data),
        image.cols,image.rows,image.cols*image.channels(),QImage::Format_Indexed8);
    }
    //显示在label中:voidsetPixmap(constQPixmap&);
    ui->label->setPixmap(QPixmap::fromImage(img));
    //改变label的尺寸已自适应图像
    ui->label->resize(ui->label->pixmap()->size());

  然后再去打开图片,可以了。但是还有个问题就是,为什么打开256x256的图片的时候,本来图片本身没有边框的,打开后就加了个边框呢???这个是在cv::Mat 打开的时候就有了,从这里找原因。将同样为256x256大小的原图,在其基础上的边框上加了一个点:

  测试后没有边框了,因此跟图片大小没关系。查了一些资料,不知道是不是跟png的alpha通道有关?那接下来只要查看每个图片是不是有alpha通道就行了(其他的图片都是用了WIN7自带的画图工具对256x256原始图片来更改保存的,所以在这个过程中可能改变了原图的alpha通道,RGB,像PS软件会保存alpha通道,RGBA)。
  png如果有第四个通道alpha,也就是每个像素是32位了,都是uchar型,第四个通道是处理透明度的,0~255,0为完全透明,255为不透明。
  所以有边框的结果是第四通道叠加到原图上去了。OpenCV 2.3以后的版本支持alpha通道,所以也就能够打开。但是打开一张图片的函数imread()的第二个参数是可以设置能够打开4通道的png图片的。测试了下,256x256和基于这个修改的图片的通道数都是4。这下我也不知道怎么解决了,最后尝试了在显示之前将4通道的转为3通道的,但是也未能解决。

    //读取4通道的图片,CV_LOAD_IMAGE_UNCHANGED=-1
    cv::imread(fileName.toUtf8().data(), CV_LOAD_IMAGE_UNCHANGED);
    //获取通道数
    if(image.channels() == 4){
        //先转换,但是试过了也不行
        cv::cvtColor(image,image,CV_BGRA2BGR);
        cv::namedWindow("Original Image");
        cv::imshow("Original Image",image);
    }

总得来说,在计算机视觉处理中,alpha通道接触是比较少的,所以还是没继续深究了,以后有机会了再来把这个框的原因彻底搞清楚。

续:
听了博主shiter的建议,再去鼓捣了下,这里写下过程:
  我将原始的png图片命名为source.png,然后用imread,设置第二个参数为-1去读取图片,然后将图片数据打印了出来,因为是四通道的,所以256x256图像每行的8位数据为1024个(BGRA)。分析了前几行,发现A通道(设置透明度的)的值都为0。
  第二个测试是基于source.png图片用win7自带画图工具在边框上加了个点(大小保持不变):

OpenCV【2】---读取png图片显示到QT label上的问题_第8张图片

  然后以同样的方式再去打印这个图片的数据,发现第四个通道的A值都为255,我立马想到要不将source.png读出来的数据的第四个通道的值全部改为255:

    cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>();
    cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>();
    for(;it != itend;++it){
        (*it)[3] = 255;
    }

  然后用imshow和QT的label分别去显示出来,居然跟没改数据一模一样。。。这下醉了(我打印了改了之后的图片数据,确定是改了)。

你可能感兴趣的:(png,opencv,Alpha,qt5,imread)