Esta página irá trazer como fazer conversões de imagens programaticamente ou via alguns programas utilitários. As conversões que esta seção se refere são de três tipos.
- conversão de um tipo de formato de imagem para outro (Ex. gif para PNG)
- Conversão de uma dada codificação de cor para outra (Exs. RGB para CMYK, RGB888 para escala de cinza)
- Conversão da estrutura de dados que suporta imagem de uma API para a equivalente de outra API (Ex. QImage para wxImage)
Cada seção desta página usara os números 1, 2 e 3 em sua descrição para se referir em relação à lista dada, qual tipo de conversão está sendo realizada.
Table of Contents
|
Conversão de QImage para IplImage
Tipo de conversão de imagem
QImage é a representação de uma imagem feita pelo Qt
iplImage é a representação de uma imagem feita pelo OpenCV
Como a conversão de imagens é entre duas APIs diferentes este tipo de conversão é a de nº 3 conforme a lista dada anteriormente
Utilidade
A utilidade desta conversão é quando você quer fazer a integração das APIs OpenCV e Qt, sendo que dois usos no contexto de desenvolvimento de jogos seriam:
- Desenvolver um jogo com realidade aumentada ou que use algumas das características do OpenCV
- Desenvolver uma ferramenta de suporte para o desenvolvimento de jogos e que tenha de fazer a integração entre Qt e OpenCV
Conversão
A conversão dada aqui foi obtida através da página http://snipplr.com/view.php?codeview&id=40277
Arquivo Conversion.h
// taken out from http://snipplr.com/view.php?codeview&id=40277 /*---------------------------------------------------------------* * Interface between Qt images and OpenCV images * * Filename : qtipl.h * * Creation : 23 April 2003 * * Authors : Rémi Ronfard, David Knossow and Matthieu Guilbert * *---------------------------------------------------------------*/ #ifndef CONVERSION_H #define CONVERSION_H #include <qimage.h> #include <iostream> #include <cstring> #include <opencv/cv.h> typedef unsigned short uint16_t; using std::string; using std::iostream; QImage *IplImageToQImage( const IplImage* iplImage, uchar** data, double mini=0.0, double maxi=0.0); IplImage *QImageToIplImage(const QImage * qImage); #endif // CONVERSION_H
Arquivo Conversion.cpp
/*---------------------------------------------------------------* * Interface between Qt images and OpenCV images * * Filename : qtipl.cpp * * Creation : 23 April 2003 * * Authors : Rémi Ronfard, David Knossow and Matthieu Guilbert * *---------------------------------------------------------------*/ #include "Conversion.h" inline int align(int size, int align) { return (size + align - 1) & -align; } IplImage *QImageToIplImage(const QImage * qImage) { int width = qImage->width(); int height = qImage->height(); CvSize Size; Size.height = height; Size.width = width; IplImage *charIplImageBuffer = cvCreateImage(Size, IPL_DEPTH_8U, 1); char *charTemp = (char *) charIplImageBuffer->imageData; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int index = y * width + x; charTemp[index] = (char) qGray(qImage->pixel(x, y)); } } return charIplImageBuffer; } /* Usage: uchar *data; QImage *qImg = IplImageToQImage(iplImg, &data); QPixmap pix = QPixmap::fromImage(*qImg); pixmapLabel->setPixmap(pix); delete qImg; cvReleaseImage(&iplImg); */ QImage *IplImageToQImage(const IplImage * iplImage, uchar **data, double mini, double maxi) { uchar *qImageBuffer = NULL; int width = iplImage->width; // Note here that OpenCV image is stored so that each lined is // 32-bits aligned thus * explaining the necessity to "skip" // the few last bytes of each line of OpenCV image buffer. int widthStep = iplImage->widthStep; int height = iplImage->height; switch (iplImage->depth) { case IPL_DEPTH_8U: if (iplImage->nChannels == 1) { // IplImage is stored with one byte grey pixel. // We convert it to an 8 bit depth QImage. qImageBuffer = (uchar *) malloc(width*height*sizeof(uchar)); uchar *QImagePtr = qImageBuffer; const uchar *iplImagePtr = (const uchar *)iplImage->imageData; for (int y = 0; y < height; y++) { // Copy line by line memcpy(QImagePtr, iplImagePtr, width); QImagePtr += width; iplImagePtr += widthStep; } } else if (iplImage->nChannels == 3) { // IplImage is stored with 3 byte color pixels (3 channels). // We convert it to a 32 bit depth QImage. qImageBuffer = (uchar *) malloc(width*height*4*sizeof(uchar)); uchar *QImagePtr = qImageBuffer; const uchar *iplImagePtr = (const uchar *) iplImage->imageData; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // We cannot help but copy manually. QImagePtr[0] = iplImagePtr[0]; QImagePtr[1] = iplImagePtr[1]; QImagePtr[2] = iplImagePtr[2]; QImagePtr[3] = 0; QImagePtr += 4; iplImagePtr += 3; } iplImagePtr += widthStep-3*width; } } else { qDebug("IplImageToQImage: image format is not supported:\ depth=8U and %d channels\n", iplImage->nChannels); } break; case IPL_DEPTH_16U: if (iplImage->nChannels == 1) { // IplImage is stored with 2 bytes grey pixel. // We convert it to an 8 bit depth QImage. qImageBuffer = (uchar *) malloc(width*height*sizeof(uchar)); uchar *QImagePtr = qImageBuffer; const uint16_t *iplImagePtr = (const uint16_t *)iplImage->imageData; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // We take only the highest part of the 16 bit value. // It is similar to dividing by 256. *QImagePtr++ = ((*iplImagePtr++) >> 8); } iplImagePtr += widthStep/sizeof(uint16_t)-width; } } else { qDebug("IplImageToQImage: image format is not supported:\ depth=16U and %d channels\n", iplImage->nChannels); } break; case IPL_DEPTH_32F: if (iplImage->nChannels == 1) { // IplImage is stored with float (4 bytes) grey pixel. // We convert it to an 8 bit depth QImage. qImageBuffer = (uchar *) malloc(width*height*sizeof(uchar)); uchar *QImagePtr = qImageBuffer; const float *iplImagePtr = (const float *) iplImage->imageData; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uchar p; float pf = 255 * ((*iplImagePtr++) - mini) / (maxi - mini); if (pf < 0) p = 0; else if (pf > 255) p = 255; else p = (uchar) pf; *QImagePtr++ = p; } iplImagePtr += widthStep/sizeof(float)-width; } } else { qDebug("IplImageToQImage: image format is not supported:\ depth=32F and %d channels\n", iplImage->nChannels); } break; case IPL_DEPTH_64F: if (iplImage->nChannels == 1) { // OpenCV image is stored with double (8 bytes) grey pixel. // We convert it to an 8 bit depth QImage. qImageBuffer = (uchar *) malloc(width*height*sizeof(uchar)); uchar *QImagePtr = qImageBuffer; const double *iplImagePtr = (const double *) iplImage->imageData; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uchar p; double pf = 255 * ((*iplImagePtr++) - mini) / (maxi - mini); if (pf < 0) p = 0; else if (pf > 255) p = 255; else p = (uchar) pf; *QImagePtr++ = p; } iplImagePtr += widthStep/sizeof(double)-width; } } else { qDebug("IplImageToQImage: image format is not supported:\ depth=64F and %d channels\n", iplImage->nChannels); } break; default: qDebug("IplImageToQImage: image format is not supported: depth=%d\ and %d channels\n", iplImage->depth, iplImage->nChannels); } QImage *qImage; if (iplImage->nChannels == 1) { QVector<QRgb> colorTable; for (int i = 0; i < 256; i++) { colorTable.push_back(qRgb(i, i, i)); } qImage = new QImage(qImageBuffer, width, height, QImage::Format_Indexed8); qImage->setColorTable(colorTable); } else { qImage = new QImage(qImageBuffer, width, height, QImage::Format_RGB32); } *data = qImageBuffer; return qImage; }