使用QT读取图像时与使用opencv读取图像还是有一定差别的,QImage读取图像时如果使用默认的方式读取
QImage image = QImage(path);
则读取的图像默认会是四通道的图像,类型为QImage::Format_ARGB32,也就是说qt会默认的对图像增加alpha通道,并且图像都是以彩色图的形式被读进来的。
opencv读取图像的默认形式
cv::Mat mat = cv::imread(path);
此时opencv将会以彩色图的形式进行读取,也就是默认的参数是1,如果希望以灰度图的形式进行读取则要使用参数0。
当希望用OpenGL进行纹理的载入的时候,QT会提供一个转化函数
QImage tex = QGLWidget::convertToGLFormat(image);
利用这个函数可以将QT读取的图像转化为OpenGL纹理需要的格式,虽然仍然以QImage的方式存储,但是已经不是QT所需要的格式,而是以OpenGL的形式存储。(简单的说就是把bgr换成rgb的形式,同时对图像进行一次翻转。其中应该还有一些不同)
OpenGL格式的纹理默认是从左下角开始的,也就是说跟正常的图像是反着的,所以QT提供的函数会将图像翻过来,贴图的时候会是正的。
同样这个函数在转化的时候会将图像以四通道的形式进行转化,也就是说会默认带有alpha通道。这一点是要注意的,因为OpenGL对纹理的原始格式是有要求的,指定转化目标类型可以与原始类型不同,但是原始类型一定要与原始图像相匹配,否则显示时纹理会变得很奇怪。
另外,我在利用QImage向Mat转化的时候发现不能使用
cv::Mat src(currentImage.height(), currentImage.width(), CV_8UC4, (void*)(QGLWidget::convertToGLFormat(qimage).bits()));
cv::Mat dst;
cvtColor(src, dst, CV_BGRA2BGR);//此时颜色转化会报错
但是可以这样写
QImage temp = QGLWidget::convertToGLFormat(currentImage);
cv::Mat src(currentImage.height(), currentImage.width(), CV_8UC4, (void*)temp.bits());
cv::Mat dst;
cvtColor(src, dst, CV_BGRA2BGR);
这样写就不会报错。原因很可能是在于QImage和OpenGL在qt中还是有不同的地方,不能直接使用。
QImage中存在一种比较特殊的图,Format_Indexed8格式是一个索引图,其中保存的是对应rgb颜色组的索引值(目的应该是为了节省空间和加快速度)。这个格式在转换为Mat的灰度图的过程中应该是进行了一次隐式的转化,将图像的格式转化为了Format_Grayscale8,然后转化为了Mat,这样就保持了一致。我测试了转化前后的类型,发现类型发生了改变,应该是自动进行了转化的计算。(其中QImage应该是通过一个公式将rgb颜色转化为了灰度图,因为Format_Indexed8本身是可以显示彩色图的)。