如何将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)
{
}
答案 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);