opencv常用函数,QT中Mat与QImage的转换

一、opencv简介

opencv是一个跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上,实现了图像处理和计算机视觉方面的很多通用算法。

二、cv常用函数

1.imread

Mat imread( const String& filename, int flags = IMREAD_COLOR );是从指定文件载入一幅图像

filename:要读入图片的完整路径

flags:读入图片的标志

IMREAD_UNCHANGED = -1,表示读取原图,包括alpha通道, 不进行任何改变

IMREAD_GRAYSCALE = 0,表示以灰度图方式读取原图

IMREAD_COLOR = 1,表示以RGB方式读取原图,忽略alpha通道,默认参数

这里需要注意:读取图片时默认是忽略透明度,打开一个背景颜色为透明的图片时会是黑色。如果想要透明度,使用IMREAD_UNCHANGED = -1参数。

2.imwrite

bool imwrite( const String& filename, InputArray img,const std::vector<int>& params = std::vector<int>());是保存一幅图像到指定的文件中。

filename:所需保存图像的文件目录和文件名。这里的文件名需要带有图像格式后缀的,目前OpenCV该函数只支持JPEG,PNG,PPM,PGM,PBM,TIFF等。并不是所有Mat类型都支持。

img:图像数据来源,其类型为Mat。

3.imdecode

Mat imdecode( InputArray buf, int flags );是从指定的内存缓存中读一幅图像

buf:它是以字节为单位接收到的图像数据

flags:它指定读取图像的方式。默认值为IMREAD_COLOR 同(1)中类型

4.imencode

bool imencode( const String& ext, InputArray img,CV_OUT std::vector<uchar>& buf,const std::vector<int>& params = std::vector<int>());是将一幅图像写进内存缓存中。

ext:定义输出文件格式的扩展名

img:需要被编码的图像

buf:输出的缓存区,类型是vector

parms:被编码的格式和压缩率,类型是vector

prams目前支持以下参数:

JPEG,它的压缩率范围(cv_imwrite_jpeg_quality)从0到100(越大越好)。默认值是95。100为没有压缩。

对于WEBP来说,它的压缩范围(cv_imwrite_webp_quality)从1到100(越大越好)。默认情况下(不含任何参数)和质量在100以上,则使用无损压缩。

png,可以压缩级别(cv_imwrite_png_compression)从0到9。更高的值意味着更小的尺寸和更长的压缩时间。默认值是3。

PPM、PGM、或PBM,它可以是一个二进制格式的标志(cv_imwrite_pxm_binary),0或1。默认值是1。

5.cvtColor

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );

src:输入图像即要进行颜色空间变换的原图像,可以是Mat类

dst:输出图像即进行颜色空间变换后存储图像,也可以Mat类

code:转换的代码或标识,表示图像转码方式 ,比如:CV_BGR2RGB

dstCn:目标图像通道数,如果取值为0,则由src和code决定

三、Mat常用构造函数

1.Mat::Mat()

无参数构造方法

2.Mat::Mat(int rows, int cols, int type)

创建行数为 rows,列数为 col,类型为 type 的图像

3.Mat::Mat(Size size, int type)

创建大小为 size,类型为 type 的图像

Size(cols,rows)在Size()的构造函数中行数和列数在是反过来的

4.Mat::Mat(int rows, int cols, int type, const Scalar& s)

创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化为值 s

5.Mat::Mat(Size size, int type, const Scalar& s)

创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s

6.Mat::Mat(const Mat& m)

将m赋值给新创建的对象,此处不会对图像数据进行复制,m和新对象共用图像数据,属于浅拷贝

四、类似“CV_8UC3”的含义

1.8U还包括{8U,16S,16U,32S,32U,32F}多种类别。

U:无符号整形  

S:有符号整形

F:单精度浮点型

8U:8位无符号整形 (0~255)

8S:8位符号整形 (-128~127)

16U:16位无符号整形 (0~65535)

16S:16位有符号整形 (-32768~32767)

32S:32位有符号整形 (-2147483648~2147483647)

32F:32位浮点数 (-FLT_MAX ………FLT_MAX,INF,NAN)

64F:64 位浮点数 (-DBL_MAX ……….DBL_MAX,INF,NAN)

例如:CV_32FC2:32位浮点型双通道矩阵

2.C3 还包括{C1,C3,C4}

C:通道,多通道排列顺序为BGR

C1:单通道,灰度图

C3:三通道,BGR图像

C4:四通道,BGRA图像

如果需要更多的通道数,需要用宏 CV_8UC(n)。例如:CV_8UC(6)

五、cv::Mat与QImage的互相转换

1.QImage转cv::Mat

cv::Mat QImageTocvMat(const QImage &image)
{
    cv::Mat mat;
    switch(image.format())
    {
    case QImage::Format_Grayscale8: //灰度图,每个像素点1个字节(8位)
    case QImage::Format_Indexed8: //Mat构造:行数,列数,存储结构,数据,step每行多少字节
                mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
    break;
    case QImage::Format_ARGB32: 
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32_Premultiplied:
                mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
    break;
    case QImage::Format_RGB888: //RR,GG,BB字节顺序存储
                mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
                cv::cvtColor(mat, mat, cv::COLOR_RGB2BGR); //opencv需要转为BGR的字节顺序
        break;
    }
    return mat;
}

2.cv::Mat转QImage

QImage cvMatToQImage(const cv::Mat& mat)
{
    switch (mat.type()) {
    case CV_8UC1:{
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);

        image.setColorCount(256);
        for(int i = 0; i < 256; i++){
            image.setColor(i, qRgb(i, i, i));
        }

        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++){
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }

        return image;
    }
        break;
    case CV_8UC3:{
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);

        return image.rgbSwapped();
    }
        break;
    case CV_8UC4:{
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);

        return image.copy();
    }
        break;
    default:
        break;
    }

    return QImage();
}

六、例子

QImage cvMatToQImage(const cv::Mat& mat)
{
    switch (mat.type()) {
    case CV_8UC1:{
        qDebug()<<"CV_8UC1";
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);

        image.setColorCount(256);
        for(int i = 0; i < 256; i++){
            image.setColor(i, qRgb(i, i, i));
        }

        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++){
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }

        return image;
    }
        break;
    case CV_8UC3:{
        qDebug()<<"CV_8UC3";
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);

        return image.rgbSwapped();
    }
        break;
    case CV_8UC4:{
        qDebug()<<"CV_8UC4";
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);

        return image.copy();
    }
        break;
    default:
        break;
    }

    return QImage();
}

void MainWindow::on_pushButton_clicked()
{
    QString img_name = QFileDialog::getOpenFileName( this, tr("Open Image"), ".", tr("Image Files(*.png *.jpg *.jpeg *.bmp)"));
    cv::Mat src = cv::imread(img_name.toStdString(),-1);

    QPixmap video = QPixmap::fromImage(cvMatToQImage(src));

    ui->label->resize( video.size());
    ui->label->setPixmap( video);
}

注意:之前用imread函数读取图片时,没有写后面的枚举值,用的默认值1,默认不读取透明度,结果读出来的背景透明色的图片背景都是黑色的,找了好几天原因。网上的例子都是没有写默认值的,读出来的图片都是没有问题的,一度怀疑自己。结果是这个默认值的问题,写-1的话是读取透明度的,网上例子没有问题是因为读取的图片背景颜色不是透明的,不涉及到透明度问题。

猜你喜欢

转载自blog.csdn.net/m0_67254672/article/details/128735617