从OpenImageIO ImageBuf到OpenCV IplImage的输出图像被破坏

时间:2016-10-29 18:27:40

标签: c++ opencv

我正在将OpenImageIO ImageBufs的转换器写入OpenCV IplImages。运行以下代码会导致输出图像损坏(下图)。我正在处理OpenImageIO的拉取请求,但是如果来自OpenCV社区的人对OpenCV方面有一些见解,那将是非常有帮助的。 OpenImageIO Pull Request

代码

IplImage *
ImageBufAlgo::to_IplImage (const ImageBuf &src)
{
#ifdef USE_OPENCV
    const ImageSpec &spec = src.spec();
    const ImageBuf *tmp = &src;
    ImageBuf localcopy;
    int channels = std::min(spec.nchannels, 4);

    // If the image has 4+ channels, then reduce to 4 channels, and use BGRA
    // order (OpenCV ordering).
    if (channels >=3) {
        // OpenCV images support up to 4 channels (BGRA)
        int channelorder[channels];

        // Set the channel order
        for (int i = 0; i < channels; ++i) {
            channelorder[i] = i;
        }

        channelorder[0] = 2;  // B
        channelorder[1] = 1;  // G
        channelorder[2] = 0;  // R

        if (!ImageBufAlgo::channels(localcopy, src, channels, &channelorder[0])) {
            DASSERT (0 && "Could not swap channels.");
            return NULL;
        }
        tmp = &localcopy;
    }

    // Create an IplImage to write to.
    CvSize size = cvSize(spec.width, spec.height);
    IplImage *dst;

    // Get the pixel data from the ImageBuf and send it to the IplImage.
    switch (spec.format.basetype) {
        case TypeDesc::UINT8: {
            dst = cvCreateImageHeader(size, IPL_DEPTH_8U, channels);

            if (!dst) {
                DASSERT (0 && "Could not create dst IplImage.");
                return NULL;
            }

            if (tmp->storage() != ImageBuf::IMAGECACHE) {
                // Type is right and the IB is not backed by an ImageCache, so
                // directly read from the local data of the IB.
                cvSetData(dst, (void *)tmp->localpixels(), dst->widthStep);
            } else {
                // Either we are backed by an ImageCache, or we somehow still
                // need a data format conversion, so make a local copy with
                // get_pixels.
                std::vector<unsigned char> data;
                data.resize (spec.width * spec.height * spec.depth * channels);
                tmp->get_pixels (ROI::All(), TypeDesc::INT8, &data[0]);
                cvSetData(dst, &data[0], dst->widthStep);
            }

            break;
        default:
            DASSERT (0 && "unknown TypeDesc");
            return NULL;
    }

    return dst;
#else
    return NULL;
#endif
}

测试代码

#include <ostream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core_c.h>
#include <opencv2/highgui/highgui_c.h>
#include <OpenImageIO/imagebuf.h>
#include <OpenImageIO/imagebufalgo.h>

namespace oiio = OpenImageIO;

int main(int argc, char const *argv[]) {
  oiio::ImageBuf src("/home/scott/Projects/oiio-test/images/input.jpg");
  IplImage *dst = oiio::ImageBufAlgo::to_IplImage(src);
  cvSaveImage("/home/scott/Projects/oiio-test/images/output.jpg", dst);

  return 0;
}

输入图像

图片1

input

图片2

input2

输出图像

图片1

output

图片2

output2

我目前的理论

  • 数据的布局方式有所不同。据我所知,OpenCV期望一个3通道图像布局BGRBGRBGR ...我认为默认情况下,OpenImageIO的布局是RGBRGBRGB ...,但确实会被交换。我没有添加任何填充,因此数据中已有填充,或者我遗漏了一些内容。
  • 我将错误的步骤传递给cvSetData(步骤计算:row * type size * channels)。我尝试手动设置一些值但是我得到的结果更糟,或者OpenCV引发异常和段错误。

还有别的我可能做错了吗?

0 个答案:

没有答案