始:在项目中需要用opencv将视频流抠出需要的区域后进行实时显示到osg中,在测试过程中发现用mat保存后的png文件可以在osg中正常显示,内存数据则不行
过程:
1.抠图
bool CuseMat::makeContours(cv::Mat &mat, cv::Mat &matRoi, std::vector<std::vector<cv::Point>> contours)
{
cv::Mat _matRoi = cv::Mat::zeros(mat.size(), CV_8UC1);;
cv::drawContours(_matRoi, contours, 0, cv::Scalar(255), -1);
cv::Mat tmp;
mat.copyTo(tmp, _matRoi);
toPng(tmp, matRoi, 0);
return true;
}
void CuseMat::toPng(cv::Mat &src, cv::Mat &dst, int mark)
{
cv::Mat cv_input = src.clone();
if (cv_input.channels() != 4)
{
cv::cvtColor(cv_input, dst, CV_BGR2BGRA);
}
else
{
return;
}
for (int y = 0; y < dst.rows; ++y)
{
for (int x = 0; x < dst.cols; ++x)
{
cv::Vec4b & pixel = dst.at<cv::Vec4b>(y, x);
if (pixel[0] == mark && pixel[1] == mark && pixel[2] == mark)
{
pixel[3] = 0;
}
}
}
}
2.osg显示图片
void setImageData(unsigned char* data, int cols, int rows, int internalFormat = GL_RGB8, int pixelFormat = GL_RGB)
{
if (image)
{
image->setImage(cols, rows, 1, internalFormat, pixelFormat, GL_UNSIGNED_BYTE, (BYTE*)data, osg::Image::NO_DELETE, 1);
image->dirty();
}
}
3.测试内存方式 --失败
dt.umat.makeContours(dt.tmat, dt.roimat, { {{142,421}, {285,255},{432,380} } });
simpleVieoProject->setImageData(dt.roimat.data, dt.roimat.cols, dt.roimat.rows, GL_RGBA, GL_RGBA);
4.测试文件方式 -- 成功
tempImage = osgDB::readImageFile(testImage);
setImageData(tempImage->data(), tempImage->s(), tempImage->t(), tempImage->getInternalTextureFormat(), tempImage->getPixelFormat());
5.查找资料
to osg -- jpg
https://blog.youkuaiyun.com/SJTU_dodoro/article/details/40111067
https://blog.youkuaiyun.com/qq_30547073/article/details/82823848
https://blog.youkuaiyun.com/qq_23191991/article/details/51036051
....
最终 参考 png -----
https://blog.youkuaiyun.com/tajon1226/article/details/90605051
6.测试网上代码 -- 成功 --png
osg::ref_ptr<osg::Image> CVMat_2_OSGImage(cv::Mat& cvimg)
{
unsigned char* data = cvimg.data;
int width = cvimg.cols;
int height = cvimg.rows;
int bytesPerLine = static_cast<int>(cvimg.step);
switch (cvimg.type())
{
case CV_8UC4:
{
osg::Image* osgframe = new osg::Image();
osgframe->setImage(cvimg.cols, cvimg.rows, 1,
GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, data, //GL_BGRA //cvimg.data GL_RGBA8
osg::Image::NO_DELETE, bytesPerLine);
return osgframe;
}
default:
{
return NULL;
}
}
}
tcvImg = cv::imread(testImage, cv::IMREAD_UNCHANGED);
tempImage = CVMat_2_OSGImage(tcvImg);
结: mat的png的data数据排列方式与osg image data的png内部排列方式不同,所以osg展示mat的png数据存在问题