#qt #opencv #qimage #iplimage
#qt #opencv #qimage #iplimage
Вопрос:
Я хотел бы отображать изображение в окне qt, поэтому я использовал Qlabel-> setpixmap
но как я могу преобразовать из IplImage в QImage, чтобы отобразить его в ярлыке??
Я нашел следующую функцию для ее преобразования, но я не знал, как использовать ее в инструкции call
QImage *IplImageToQImage(const IplImage * iplImage, uchar **data, double mini, double maxi)
{
uchar *qImageBuffer = NULL;
int width = iplImage->width;
int widthStep = iplImage->widthStep;
int height = iplImage->height;
switch (iplImage->depth)
{
case IPL_DEPTH_8U:
if (iplImage->nChannels == 1)
{
// OpenCV image 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)
{
/* OpenCV image 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 channelsn", iplImage->nChannels);
}
break;
case IPL_DEPTH_16U:
if (iplImage->nChannels == 1)
{
/* OpenCV image 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 *);
const unsigned int *iplImagePtr = (const unsigned int *)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(unsigned int)-width;
}
}
else
{
qDebug("IplImageToQImage: image format is not supported : depth=16U and %d channelsn", iplImage->nChannels);
}
break;
case IPL_DEPTH_32F:
if (iplImage->nChannels == 1)
{
/* OpenCV image 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 channelsn", 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;
}
}
}
else
{
qDebug("IplImageToQImage: image format is not supported : depth=64F and %d channelsn", iplImage->nChannels);
}
break;
default:
qDebug("IplImageToQImage: image format is not supported : depth=%d and %d channelsn", iplImage->depth, iplImage->nChannels);
}
QImage *qImage;
QVector<QRgb> vcolorTable;
if (iplImage->nChannels == 1)
{
// We should check who is going to destroy this allocation.
QRgb *colorTable = new QRgb[256];
for (int i = 0; i < 256; i )
{
colorTable[i] = qRgb(i, i, i);
vcolorTable[i] = colorTable[i];
}
qImage = new QImage(qImageBuffer, width, height, QImage::Format_Indexed8);
qImage->setColorTable(vcolorTable);
}
else
{
qImage = new QImage(qImageBuffer, width, height, QImage::Format_RGB32);
}
*data = qImageBuffer;
return qImage;
}
Параметр был:
const IplImage * IplImage, учет ** данных, двойное мини, двойное макси
что такое данные, мини, макс? как я могу получить это из моего IplImage, чтобы использовать его в инструкции call?
Большое спасибо
Комментарии:
1. Я только что обнаружил ошибку в коде!! IPL_DEPTH_16U «const unsigned int» следует заменить там на «const unsigned short»
Ответ №1:
Похоже, что data
не используется кодом, а mini
и maxi
используются для преобразования значений с плавающей запятой, которые используют определенные форматы изображений, в целочисленные значения в диапазоне 0-255.
Я бы попробовал использовать NULL для данных. mini
и maxi
действительно зависят от данных изображения, и я не знаю, каковы разумные диапазоны. Но если ваш IplImage не хранится в виде значений с плавающей запятой, то эти значения не должны иметь никакого значения.
Комментарии:
1. извините, я справился с неполным кодом, он использовался в буфере *data = QImage; где я могу его получить? и является ли обновленный qimage приемлемым в setpixmap? Спасибо.
2. Код вызывает
qImage = new QImage(qImageBuffer...
и возвращает qImageBuffer вdata
. Если вам не интересно, вы можете просто удалить эту строку и параметр из функции. Что касается того, работает это или нет — я предлагаю вам попробовать. Боюсь, я никогда не использовал OpenCV.3. Я попробовал это с пропущенной строкой, как вы сказали, возникает ошибка во время выполнения: Microsoft visual C Runtime Library. Это приложение запросило среду выполнения завершить его необычным способом. если я напишу ui-> label-> setpixmap (Qpixmap::FromImage(qimg)), появится сообщение об ошибке: нет соответствующей функции для вызова Qpixmap :: FromImage (QImage * amp;), как можно решить эти проблемы. спасибо.
Ответ №2:
Вы можете просто создать QImage, где данные принадлежат чему-то другому (например, IplImage), используя QImage (данные, ширина, высота, формат), а данные — это данные IplImage ptr, если формат одинаков как в QImage, так и в IplImage (например, RGB888 = 8U_C3)
Ответ №3:
Я обнаружил некоторые ошибки в коде …. возможно, в нем есть еще больше ошибок, но пока для меня все выглядит нормально. Для QImage с Format_Index8 иногда требуется (в зависимости от разрешения изображения ….) добавить 2 байта с правой стороны (не знаю почему, но похоже, что это так). Вот новый адаптированный код
QImage *IplImageToQImage(const IplImage * iplImage, uchar **data, double mini, double maxi)
{
uchar *qImageBuffer = NULL;
int width = iplImage->width;
int widthStep = iplImage->widthStep;
int height = iplImage->height;
QImage *qImage;
switch (iplImage->depth)
{
case IPL_DEPTH_8U:
if (iplImage->nChannels == 1)
{
// OpenCV image is stored with one byte grey pixel. We convert it
// to an 8 bit depth QImage.
qImage = new QImage(width,height,QImage::Format_Indexed8);
uchar *QImagePtr = qImage->scanLine(0);
qImageBuffer = qImage->scanLine(0);
const uchar *iplImagePtr = (const uchar *) iplImage->imageData;
for (int y = 0; y < height; y )
{
// Copy line by line
QImagePtr = qImage->scanLine(y);
memcpy(QImagePtr, iplImagePtr, width);
iplImagePtr = widthStep;
}
/*
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);
*QImagePtr = *iplImagePtr;
QImagePtr ;
iplImagePtr ;
}
iplImagePtr = widthStep/sizeof(uchar)-width;
}*/
}
else if (iplImage->nChannels == 3)
{
/* OpenCV image 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 channelsn", iplImage->nChannels);
}
break;
case IPL_DEPTH_16U:
if (iplImage->nChannels == 1)
{
/* OpenCV image is stored with 2 bytes grey pixel. We convert it
to an 8 bit depth QImage.
*/
qImage = new QImage(width,height,QImage::Format_Indexed8);
uchar *QImagePtr = qImage->scanLine(0);
qImageBuffer = qImage->scanLine(0);
//const uint16_t *iplImagePtr = (const uint16_t *);
const unsigned short *iplImagePtr = (const unsigned short *)iplImage->imageData;
for (int y = 0; y < height; y )
{
QImagePtr = qImage->scanLine(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);
//change here 16 bit could be everything !! set max min to your desire
*QImagePtr = 255*(((*iplImagePtr) - mini) / (maxi - mini));
QImagePtr ;
iplImagePtr ;
}
iplImagePtr = widthStep/sizeof(unsigned short)-width;
}
}
else
{
qDebug("IplImageToQImage: image format is not supported : depth=16U and %d channelsn", iplImage->nChannels);
}
break;
case IPL_DEPTH_32F:
if (iplImage->nChannels == 1)
{
/* OpenCV image is stored with float (4 bytes) grey pixel. We
convert it to an 8 bit depth QImage.
*/
qImage = new QImage(width,height,QImage::Format_Indexed8);
uchar *QImagePtr = qImage->scanLine(0);
qImageBuffer = qImage->scanLine(0);
const float *iplImagePtr = (const float *) iplImage->imageData;
for (int y = 0; y < height; y )
{
QImagePtr = qImage->scanLine(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 channelsn", 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.
*/
qImage = new QImage(width,height,QImage::Format_Indexed8);
uchar *QImagePtr = qImage->scanLine(0);
qImageBuffer = qImage->scanLine(0);
const double *iplImagePtr = (const double *) iplImage->imageData;
for (int y = 0; y < height; y )
{
QImagePtr = qImage->scanLine(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;
}
}
}
else
{
qDebug("IplImageToQImage: image format is not supported : depth=64F and %d channelsn", iplImage->nChannels);
}
break;
default:
qDebug("IplImageToQImage: image format is not supported : depth=%d and %d channelsn", iplImage->depth, iplImage->nChannels);
}
QVector<QRgb> vcolorTable;
if (iplImage->nChannels == 1)
{
// We should check who is going to destroy this allocation.
vcolorTable.resize(256);
for (int i = 0; i < 256; i )
{
vcolorTable[i] = qRgb(i, i, i);
}
//Qt vector is difficult to use... start with std to qvector
//here I allocate QImage using qt constructor (Forma_Indexed8 adds sometimes 2 bytes on the right side !!! o.O not specified nowhere !!!)
//qImage = new QImage(tmpImg->scanLine(0), width, height, QImage::Format_Indexed8);
qImage->setColorTable(vcolorTable);
}
else
{
qImage = new QImage(qImageBuffer, width, height, QImage::Format_RGB32);
}
*data = qImageBuffer;
return qImage;
}
Я не знаю, есть ли у 3 каналов такая же ошибка, но я надеюсь, что нет