我正在使用OpenCV和Qt,Opencv使用BGR,而Qt使用RGB,所以我必须将这2个字节换成非常大的图像。
有更好的方法可以做到以下几点吗? 我想不出更快,但看起来如此简单和蹩脚......
int width = iplImage->width;
int height = iplImage->height;
uchar *iplImagePtr = (uchar *) iplImage->imageData;
uchar buf;
int limit = height * width;
for (int y = 0; y < limit; ++y) {
buf = iplImagePtr[2];
iplImagePtr[2] = iplImagePtr[0];
iplImagePtr[0] = buf;
iplImagePtr += 3;
}
QImage img((uchar *) iplImage->imageData, width, height,
QImage::Format_RGB888);
答案 0 :(得分:5)
我们目前正在Qt应用程序中处理此问题。我们发现英特尔性能基元是最快的方法。他们有极其优化的代码。在Intel ippiSwapChannels Documentation的html帮助文件中,他们提供了您正在寻找的确切示例。
有几个缺点
答案 1 :(得分:4)
我认为这看起来非常好。代码很简单不是否定。如果您想缩短它,可以使用std::swap
:
std::swap(iplImagePtr[0], iplImagePtr[2]);
您还可以执行以下操作:
uchar* end = iplImagePtr + height * width * 3;
for ( ; iplImagePtr != end; iplImagePtr += 3) {
std::swap(iplImagePtr[0], iplImagePtr[2]);
}
答案 2 :(得分:2)
cvConvertImage在一行中完成整个事情,但我怀疑它是否更快。
答案 3 :(得分:2)
您是否可以使用以下方法之一?
void QImage::invertPixels ( InvertMode mode = InvertRgb )
或
QImage QImage::rgbSwapped () const
希望这有点帮助!
答案 4 :(得分:1)
我倾向于做类似以下的事情,根据RGB数据在三个字节的块中工作。
int i = 0;
int limit = (width * height); // / 3;
while(i != limit)
{
buf = iplImagePtr[i]; // should be blue colour byte
iplImagePtr[i] = iplImagaePtr[i + 2]; // save the red colour byte in the blue space
iplImagePtr[i + 2] = buf; // save the blue color byte into what was the red slot
// i++;
i += 3;
}
我怀疑它是否“更快”但是在一天结束时,你只需逐个像素地浏览整个图像。
答案 5 :(得分:1)
您可以随时执行此操作:
int width = iplImage->width;
int height = iplImage->height;
uchar *start = (uchar *) iplImage->imageData;
uchar *end = start + width * height;
for (uchar *p = start ; p < end ; p += 3)
{
uchar buf = *p;
*p = *(p+2);
*(p+2) = buf;
}
但是一个体面的编译器无论如何都会这样做。
这些操作中最大的开销是内存带宽。
如果您使用的是Windows,则可以使用BitBlt和两个适当设置的DIB进行此转换。如果你真的很幸运,那么可以在图形硬件中完成。
答案 6 :(得分:0)
我讨厌破坏任何人的一天,但是如果你不想去IPP路线(见photo_tom)或拉入一个优化的库,你可能会从以下方面获得更好的表现(修改Andreas答案):
uchar *iplImagePtr = (uchar *) iplImage->imageData;
uchar buf;
size_t limit = height * width;
for (size_t y = 0; y < limit; ++y) {
std::swap(iplImagePtr[y * 3], iplImagePtr[y * 3 + 2]);
}
现在,伙计们,我听到你大声喊叫“但所有这些额外的倍增和增加!”问题是,这种形式的循环远更容易让编译器进行优化,特别是如果它们足够智能多线程这种算法,因为每次通过循环都独立于之前或之后的那些。在另一种形式中,iplImagePtr
的值取决于前一次传递中的值。在这种形式中,整个循环中常量;只有y
更改,这是一个非常非常常见的“从0到N-1计数”循环结构,因此优化器更容易消化。
或者这些天它没有什么不同,因为优化者非常聪明(是吗?)。我想知道基准会说什么......
P.S。如果您确实对此进行了基准测试,我还希望了解以下内容的效果:
uchar *iplImagePtr = (uchar *) iplImage->imageData;
uchar buf;
size_t limit = height * width;
for (size_t y = 0; y < limit; ++y) {
uchar *pixel = iplImagePtr + y * 3;
std::swap(pix[0], pix[2]);
}
同样,在循环中定义pixel
以限制其范围并使优化器不再认为存在循环到循环的依赖关系。如果编译器每次通过循环递增和递减堆栈指针以“创建”和“销毁”pixel
,那么,它是愚蠢的,我会因为浪费你的时间而道歉。
答案 7 :(得分:0)
cvCvtColor(iplImage, iplImage, CV_BGR2RGB);