IplImage to vector <uint8_t> </uint8_t>

时间:2014-09-30 11:02:13

标签: c++ opencv

如何将IplImage转换为vector<uint8_t>。如果我将图像路径发送到以下功能,我可以转换它:

bool faceImg::load_file (const string &path, vector<uint8_t> &data)
{
    data.clear();

    std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
    if (!is.is_open())
        return false;

    is.seekg(0, is.end);
    size_t len = (size_t)is.tellg();
    is.seekg(0, is.beg);
    data.resize(len);
    is.read((char*)data.data(), len);

    return true;
}

但是我想从相机捕捉中重写IplImage的功能:

bool faceImg::load_image(IplImage *image, vector<uint8_t> &data)
{

}

3 个答案:

答案 0 :(得分:7)

这是您想要的功能。您可以像maxint提供的版本一样优化它(但重塑可能会改变输入IplImage?!?)。

该功能应适用于任意数量的通道,但它采用8位类型(例如8位灰度图像或24位BGR图像)。

这是我的功能:

// you dont need this typedef!
typedef unsigned char uint8_t ;

// probably not the fastest way ;)
// returns a vector with this ordering:
// x=0; y=0; Blue Channel value
// x=0; y=0; Green Channel value
// x=0; y=0; Red Channel value
// x=1; y=0; Blue Channel value
// ...
bool load_image(IplImage *image, std::vector<uint8_t> &data)
{
    if(image->depth != 8) return false;

    // only allocate the memory once
    data.reserve(image->width*image->height* image->nChannels);

    unsigned char * imgPtr = (unsigned char*) image->imageData;

    for(unsigned int y=0; y<image->height; ++y)
        for(unsigned int x=0; x<image->width; ++x)
            for(unsigned int c=0; c<image->nChannels; ++c)
            {
                unsigned char * valuePtr = imgPtr + y*image->widthStep + x*image->nChannels + c;
                data.push_back(*valuePtr);
            }

    return true;
}

我用这个函数来测试:

int main()
{
    //cv::Mat input = cv::imread("../inputData/Lenna.png", CV_LOAD_IMAGE_GRAYSCALE);
    cv::Mat input = cv::imread("../inputData/Lenna.png");

    // your IplImage, this one is 24 bit BGR format
    IplImage * yourImage = &(IplImage)input;

    // your vector
    std::vector<uint8_t> data;

    // your function call to load that image to a vector
    load_image(yourImage, data);

    // unit test: check whether pixel in cv::Mat are the same as the ones in the vector
    for(unsigned int j=0; j<input.rows; ++j)
        for(unsigned int i=0; i<input.cols; ++i)
        {
            if(input.channels() == 3)
            {
                cv::Vec3b pixel = input.at<cv::Vec3b>(j,i);
                for(unsigned int c=0; c<input.channels(); ++c)
                {
                    if(pixel[c] != data[input.channels()*j*input.rows + input.channels()*i +c])
                        std::cout << "different values at: (" << i << "," << j << "): " << (int)pixel[c] << " vs " << (int)data[input.channels()*j*input.rows + input.channels()*i +c] << std::endl;
                }
            }
            else if(input.channels() == 1)
            {
                unsigned char pixel = input.at<unsigned char>(j,i);
                for(unsigned int c=0; c<input.channels(); ++c)
                {
                    if(pixel != data[input.channels()*j*input.rows + input.channels()*i +c])
                        std::cout << "different values at: (" << i << "," << j << "): " << (int)pixel << " vs " << (int)data[input.channels()*j*input.rows + input.channels()*i +c] << std::endl;
                }
            }
        }


    cvNamedWindow("IplImage");
    cvShowImage("IplImage", yourImage);


    cv::imshow("input", input);
    cv::waitKey(0);
    return 0;
}

答案 1 :(得分:2)

image.reshape(1, 1).copyTo(v);

cv::Mat(C ++ API)比OpenCV 2.0中的IplImage(C API)更受欢迎。需要reshape(),因为视频帧可能有多个频道或多个行。它不会修改原始image结构(@Micka),而是返回带有新通道和​​新行的标头结构。当图像数据连续image.step == image.width * image.elemSize()时,它仅 ONLY 。否则,请使用以下代码:

vector<uint8_t> v(image.total());
image.copyTo(Mat(image.size(), TYPE_8U, &v[0]));

<强>参考

答案 2 :(得分:2)

假设你使用cv :: Mat(并且必须),并且假设你的Mat是连续的,从数据指针中生成vector<uchar>非常容易:

Mat ocv = ...

vector<uchar> vec( ocv.data, (ocv.data + ocv.total()*ocv.elemSize()) );

如果你想要一个完整的图像,比如在磁盘上,请使用imencode

Mat ocv = ...
vector<uchar> vec;
imencode("png",ocv,vec);