Opencv和Qt QImage格式转Mat
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Opencv和Qt QImage格式转Mat相关的知识,希望对你有一定的参考价值。
目的:在Qt creator中用QImage读取内存里的一张图片,转换成cv::Mat格式(或Iplimage格式)进行图像算法处理
我实验用本地磁盘里的一张24位或者8位图像,可以顺利从QImage转成Mat,但从内存读取的图像就不行。
读取本地图片代码如下:(8位图像,只用了一个通道) QImage image("E:/Test_Picture/ver.tif");
qDebug()<<image.format();
cv::Mat mat = cv::Mat(image.height(),image.width(),
CV_8UC1, (uchar*)image.bits(), image.bytesPerLine());
cv::Mat mat2 = cv::Mat(mat.rows, mat.cols, CV_8UC1 );
int from_to[] = 0,0,1,1,2,2;
cv::mixChannels(&mat,1,&mat2,1,from_to,1);
namedWindow("QImage2Mat");
imshow("QImage2Mat",mat2);读取本地图片代码(24位,QImage4个通道转成mat三个通道):
QImage image("D:/Picture/boy.jpg");
qDebug()<<image.format();
cv::Mat mat = cv::Mat(image.height(),image.width(),
CV_8UC4, (uchar*)image.bits(), image.bytesPerLine());
cv::Mat mat2 = cv::Mat(mat.rows, mat.cols, CV_8UC3 );
int from_to[] = 0,0,1,1,2,2;
cv::mixChannels(&mat,1,&mat2,1,from_to,3);
namedWindow("QImage2Mat");
imshow("QImage2Mat",mat2);这两个都成功了,但是当我读取相机采集到内存的图片时,无论QImage以什么格式保存都报错
代码如下: QImage image(aa->m_pRawBuffer,1000,700,QImage::Format_RGB888);
Mat mat =Mat(image.height(),image.width(),
CV_8UC3, (uchar*)image.bits(), image.bytesPerLine());
Mat mat2 =Mat(mat.rows, mat.cols, CV_8UC3 );
int from_to[] = 0,0,1,1,2,2;
mixChannels(&mat,1,&mat2,1,from_to,3);
namedWindow("test");
imshow("test",mat2);
按道理说都是三个通道不应该出错啊,问题出在了哪里呢?
第三段代码中如果QImage以Format_Index8格式读取的话,只拷贝第一个通道也是可以的,但是图片的结果是全部是蓝色,也就是Mat中B这个通道。求高手解答。
或者从内存中能不能直接用Mat格式或者Iplimage格式读取,这样我就不用QImage转Mat了。
编写DetectFaceDemo.java,代码如下:
[java] view
plaincopyprint?
package com.njupt.zhb.test;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.highgui.Highgui;
import org.opencv.objdetect.CascadeClassifier;
//
// Detects faces in an image, draws boxes around them, and writes the results
// to "faceDetection.png".
//
public class DetectFaceDemo
public void run()
System.out.println("\nRunning DetectFaceDemo");
System.out.println(getClass().getResource("lbpcascade_frontalface.xml").getPath());
// Create a face detector from the cascade file in the resources
// directory.
//CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("lbpcascade_frontalface.xml").getPath());
//Mat image = Highgui.imread(getClass().getResource("lena.png").getPath());
//注意:源程序的路径会多打印一个‘/’,因此总是出现如下错误
/*
* Detected 0 faces Writing faceDetection.png libpng warning: Image
* width is zero in IHDR libpng warning: Image height is zero in IHDR
* libpng error: Invalid IHDR data
*/
//因此,我们将第一个字符去掉
String xmlfilePath=getClass().getResource("lbpcascade_frontalface.xml").getPath().substring(1);
CascadeClassifier faceDetector = new CascadeClassifier(xmlfilePath);
Mat image = Highgui.imread(getClass().getResource("we.jpg").getPath().substring(1));
// Detect faces in the image.
// MatOfRect is a special container class for Rect.
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(image, faceDetections);
System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
// Draw a bounding box around each face.
for (Rect rect : faceDetections.toArray())
Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
// Save the visualized detection.
String filename = "faceDetection.png";
System.out.println(String.format("Writing %s", filename));
Highgui.imwrite(filename, image);
package com.njupt.zhb.test;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.highgui.Highgui;
import org.opencv.objdetect.CascadeClassifier;
//
// Detects faces in an image, draws boxes around them, and writes the results
// to "faceDetection.png".
//
public class DetectFaceDemo
public void run()
System.out.println("\nRunning DetectFaceDemo");
System.out.println(getClass().getResource("lbpcascade_frontalface.xml").getPath());
// Create a face detector from the cascade file in the resources
// directory.
//CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("lbpcascade_frontalface.xml").getPath());
//Mat image = Highgui.imread(getClass().getResource("lena.png").getPath());
//注意:源程序的路径会多打印一个‘/’,因此总是出现如下错误
/*
* Detected 0 faces Writing faceDetection.png libpng warning: Image
* width is zero in IHDR libpng warning: Image height is zero in IHDR
* libpng error: Invalid IHDR data
*/
//因此,我们将第一个字符去掉
String xmlfilePath=getClass().getResource("lbpcascade_frontalface.xml").getPath().substring(1);
CascadeClassifier faceDetector = new CascadeClassifier(xmlfilePath);
Mat image = Highgui.imread(getClass().getResource("we.jpg").getPath().substring(1));
// Detect faces in the image.
// MatOfRect is a special container class for Rect.
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(image, faceDetections);
System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
// Draw a bounding box around each face.
for (Rect rect : faceDetections.toArray())
Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
// Save the visualized detection.
String filename = "faceDetection.png";
System.out.println(String.format("Writing %s", filename));
Highgui.imwrite(filename, image);
3.编写测试类:
[java] view
plaincopyprint?
package com.njupt.zhb.test;
public class TestMain
public static void main(String[] args)
System.out.println("Hello, OpenCV");
// Load the native library.
System.loadLibrary("opencv_java246");
new DetectFaceDemo().run();
//运行结果:
//Hello, OpenCV
//
//Running DetectFaceDemo
///E:/eclipse_Jee/workspace/JavaOpenCV246/bin/com/njupt/zhb/test/lbpcascade_frontalface.xml
//Detected 8 faces
//Writing faceDetection.png
package com.njupt.zhb.test;
public class TestMain
public static void main(String[] args)
System.out.println("Hello, OpenCV");
// Load the native library.
System.loadLibrary("opencv_java246");
new DetectFaceDemo().run();
//运行结果:
//Hello, OpenCV
//
//Running DetectFaceDemo
///E:/eclipse_Jee/workspace/JavaOpenCV246/bin/com/njupt/zhb/test/lbpcascade_frontalface.xml
//Detected 8 faces
//Writing faceDetection.png
opencv QImage与Mat 互转 及简单的图像处理
opencv(mat与qimage 的互转)及简单的图像处理
一、opencv库文件
编译好的opencv 库。
二、使用方式(Qt)
把上面下载的opencv.zip 解压出来的include和lib 文件夹放到工程文件夹里面,并在pro 文件中添加以下代码,即可使用
INCLUDEPATH +=$$PWD\\include
INCLUDEPATH +=$$PWD\\include\\opencv
INCLUDEPATH +=$$PWD\\include\\opencv2
LIBS +=$$PWD\\lib/libopencv_*.a
三、QImage 转 Mat (不太全,多多指教)
通过判断QImage 的类型 在调用Mat 的构造函数进行转换,代码都有进行注释
代码如下(示例):
cv::Mat ImageHandle::QImage2Mat(QImage image)
{
cv::Mat mat; //创建一个mat对象来接收
switch (image.format()) //QImage 的一个库函数 可以返回图片的类型
{
case QImage::Format_ARGB32_Premultiplied: //RGB32 为四通道的所以在调用mat构造函数需要转换成四通道的mat类型(CV_8UC4)
mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
break;
case QImage::Format_RGB888: //RGB888 即RGB24 三通道八位的图片 所以转成三通道的mat(CV_8UC4)
mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
//因为Qimage 是RGB 通道 而 Mat 为 BGR 通道 所以需要使用cvtcolor进行转换,不然图片通道会颠倒
cv::cvtColor(mat, mat,cv::COLOR_RGB2BGR);
break;
case QImage::Format_Indexed8: //Indexed8 为单通道的图片 所以在转换成mat 也是单通道(CV_8UC1)
mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
break;
}
return mat;
}
四、Mat转 QImage
跟上面一样也是通过判断mat的通道 调用QImage的构造函数来进行转换
QImage ImageHandle::Mat2QImage(cv::Mat mat)
{
if(mat.type() == CV_8UC1)
{
QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
//转换为qimage 单通道颜色值
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;
}
else if(mat.type() == CV_8UC3)
{
QImage image((const uchar*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return image.rgbSwapped();
}
else if(mat.type() == CV_8UC4)
{
const uchar *pSrc = (const uchar*)mat.data;
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
return image;
}
else
{
return QImage();
}
}
五、一些简单的图像处理操作
1、图片的滤色
通过mat的宽高来访问图片的所有像素点 并删除对应的颜色
QImage ImageHandle::ImageColorDelete(QImage &image, int flag)
{
cv::Mat mat = this->QImage2Mat(image);
cv::Mat dst = cv::Mat::zeros(mat.size(),mat.type());
int chl = mat.channels();
//遍历像素点 滤除每个像素点所对应的颜色值,从而达到滤色的效果
for(int row=0;row<mat.rows;row++)
{
for(int col=0;col<mat.cols;col++)
{
if(chl == 3)
{
switch (flag)
{
case BLUE:
dst.at<cv::Vec3b>(row,col)[0] = 0;
dst.at<cv::Vec3b>(row,col)[1] = mat.at<cv::Vec3b>(row,col)[1];
dst.at<cv::Vec3b>(row,col)[2] = mat.at<cv::Vec3b>(row,col)[2];
break;
case GREEN:
dst.at<cv::Vec3b>(row,col)[0] = mat.at<cv::Vec3b>(row,col)[0];
dst.at<cv::Vec3b>(row,col)[1] = 0;
dst.at<cv::Vec3b>(row,col)[2] = mat.at<cv::Vec3b>(row,col)[2];
break;
case RED:
dst.at<cv::Vec3b>(row,col)[0] = mat.at<cv::Vec3b>(row,col)[0];
dst.at<cv::Vec3b>(row,col)[1] = mat.at<cv::Vec3b>(row,col)[1];
dst.at<cv::Vec3b>(row,col)[2] = 0;
break;
}
}
}
}
return this->Mat2QImage(dst);
}
2、图片的反色
操作每个像素点,每个像素点的像素进行取反得到反色效果
QImage ImageHandle::ImageContraryColor(QImage &image)
{
cv::Mat mat = this->QImage2Mat(image);
cv::Mat dst = cv::Mat::zeros(mat.size(),mat.type());
int chl = mat.channels();
//操作每个像素点,每个像素点的像素进行取反得到反色效果
for(int row=0;row<mat.rows;row++)
{
for(int col=0;col<mat.cols;col++)
{
if(chl == 3)
{
dst.at<cv::Vec3b>(row,col)[0] = 255 - mat.at<cv::Vec3b>(row,col)[0];
dst.at<cv::Vec3b>(row,col)[1] = 255 - mat.at<cv::Vec3b>(row,col)[1];
dst.at<cv::Vec3b>(row,col)[2] = 255 - mat.at<cv::Vec3b>(row,col)[2];
}
}
}
return this->Mat2QImage(dst);
}
3、图像的提色
遍历像素点 提取所对应的颜色
cv::Mat mat = this->QImage2Mat(image);
cv::Mat dst = cv::Mat::zeros(mat.size(),mat.type());
int chl = mat.channels();
//遍历像素点 提取所对应的颜色
for(int row=0;row<mat.rows;row++)
{
for(int col=0;col<mat.cols;col++)
{
if(chl == 3)
{
switch (flag)
{
case BLUE:
dst.at<cv::Vec3b>(row,col)[0] = mat.at<cv::Vec3b>(row,col)[0];
dst.at<cv::Vec3b>(row,col)[1] = 0;
dst.at<cv::Vec3b>(row,col)[2] = 0;
break;
case GREEN:
dst.at<cv::Vec3b>(row,col)[0] = 0;
dst.at<cv::Vec3b>(row,col)[1] = mat.at<cv::Vec3b>(row,col)[1];
dst.at<cv::Vec3b>(row,col)[2] = 0;
break;
case RED:
dst.at<cv::Vec3b>(row,col)[0] =0;
dst.at<cv::Vec3b>(row,col)[1] = 0;
dst.at<cv::Vec3b>(row,col)[2] = mat.at<cv::Vec3b>(row,col)[2];
break;
}
}
}
}
return this->Mat2QImage(dst);
刚开始主要还是记录一下自己实现的功能,后面还会进行更新opencv 的图像处理部分
以上是关于Opencv和Qt QImage格式转Mat的主要内容,如果未能解决你的问题,请参考以下文章