从共享内存中保存 4 字节 pP 深度图像

Posted

技术标签:

【中文标题】从共享内存中保存 4 字节 pP 深度图像【英文标题】:Save 4 byte pP depth image from shared memory 【发布时间】:2017-04-19 16:13:41 【问题描述】:

到目前为止,每当我有问题时,这个社区都会帮助我,而我不必问问题,但今天我必须问我的第一个问题,因为我找不到答案,我迫切需要社区的帮助。

我正在使用一个将图像写入共享内存的模拟程序。访问内存地址,我想保存图像。模拟正在发送两张图像,一张是正常的,一张是带有深度信息的。用open cv保存普通图片没问题。

普通图片的读取和保存如下:

//find image in Memory
uchar *imageMem = (uchar*)img + sizeof( RDB_IMAGE_t );

//set heights and width to image parameters
int w = img->width;
int h = img->height;

//create matrix for image
Mat image(h,w,CV_8UC3,imageMem);

//image is upside-down in memory, so it has to be flipped
Mat flipped;
flip(image,flipped,0);

//change color from bgr to rgb
Mat recolored;
cvtColor(flipped, recolored, COLOR_BGR2RGB);

string folderName = "normal";
string name = "normal_";
string type = ".png";

ss << folderName << "/" << name << simFrame << type;

string filename = ss.str();
ss.str("");
imwrite( filename, recolored );

现在到实际问题。模拟将深度信息保存在不同的共享内存地址下,但始终保存在 img 中。根据图像的索引,指针 img 指向相应的内存地址的法线或深度。普通图像的地址是 0x0811a,深度图像的地址是 0x0811b。保存深度​​图的代码如下:

uchar *imageMem = (uchar*)img + sizeof( RDB_IMAGE_t );

int w = img->width;
int h = img->height;

Mat image_d(h,w,CV_8UC4,imageMem);

Mat flipped;
flip(image_d,flipped,0);

Mat recolored;
cvtColor(flipped, recolored, CV_BGRA2GRAY, 1);

string folderName = "Depth";
string name = "Depth_";
string type = ".png";

ss << folderName << "/" << name << simFrame << type;

string filename = ss.str();
ss.str("");
imwrite( filename, recolored );   

保存深度信息后的结果如下:

但它应该是这样的:

模拟的开发人员说深度图像作为每像素 4 字节的图像发送到共享内存,并且一个像素的值始终为 255。这些信息对我没有帮助,但也许对你有帮助。

我所知道的关于图像处理的一切都是我自己的想法,此时我真的不知道该怎么做。

Image Micka requested

【问题讨论】:

img是什么类型的? sizeof(RDB_IMAGE_t);的值是多少? 你能把 cvtColor 线去掉,把图片另存为 .png 再上传吗? 标题说“4 位深度”,文本说“每像素 4 字节”,那么它是哪一个?您也不能在每个步骤之后检查共享内存或转储它以找出损坏发生的时间吗? 大家好。谢谢你这么快回来。 @Micka:我在文本中提供了有关 img 的更多信息(刚刚编辑),RDB_IMAGE_t 的大小为 32。@VTT:标题是每像素 4 个字节的拼写错误。我认为没有早期的图像过剩。图像保存在某个内存地址 img 指向图像,我将图像写入一个开放的 cv 矩阵。然后你看到的是我添加的新图像(但没有翻转)。 THX 【参考方案1】:

如果您将提供的图像拆分为其组成通道,您会发现一些东西。

首先,它有 4 个通道 - 让我们假设它们是 R、G、B 和 A(尽管它们实际上不是)。

其次,最后两个通道是相同的 - 它们的最小/最大和标准偏差相同,因此我们可以丢弃其中一个。

Image: depth.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 800x600+0+0
  Units: Undefined
  Type: TrueColorAlpha
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    Red: 8-bit
    Green: 8-bit
    Blue: 8-bit
    Alpha: 8-bit
  Channel statistics:
    Pixels: 480000
    Red:
      min: 0 (0)
      max: 255 (1)
      mean: 181.668 (0.712422)
      standard deviation: 82.4882 (0.323483)
      kurtosis: -0.888916
      skewness: -0.74329
      entropy: 0.734481
    Green:
      min: 0 (0)
      max: 255 (1)
      mean: 175.737 (0.689165)
      standard deviation: 84.9054 (0.332963)
      kurtosis: -1.09314
      skewness: -0.611227
      entropy: 0.741165
    Blue:
      min: 229 (0.898039)                       <--- HERE
      max: 255 (1)                              <--- HERE
      mean: 252.276 (0.989316)                  <--- HERE
      standard deviation: 5.81622 (0.0228087)   <--- HERE
      kurtosis: 7.14093
      skewness: -2.88764
      entropy: 0.595817
    Alpha:
      min: 229 (0.898039)                       <--- HERE
      max: 255 (1)                              <--- HERE
      mean: 252.276 (0.989316)                  <--- HERE
      standard deviation: 5.81622 (0.0228087)   <--- HERE
      kurtosis: 7.14093
      skewness: -2.88764
      entropy: 0.595817

如果你然后提取 4 个通道,你会得到这个(首先是 R,然后是 G,然后是 B):

我认为由于最后一张图像(B 通道)只有 4-5 个波段,随着您进入图像越远,这些波段越亮,它可能是高字节。第一个图像(R通道)是带状的,所以我猜这是B通道中较大步骤之间的平滑渐变,所以我猜这是中间字节,第二个图像变化最大,所以是可能是最低有效字节。我没有做过任何测试,但我想如果你使用这样的公式,它可能会正确:

24-bit depth = (Blue<<16) | (Red<<8) | Green

例如,如果您采用该公式并在命令行中应用它(使用 ImageMagick),如下所示:

convert depth.png -fx "(((u.b*255)<<8)|(u.r*255))/65535" -auto-level  result.png

您会得到这个结果,至少在我看来,它显示了一个漂亮、平滑的深度图像。

【讨论】:

嗨,马克。我实际上发现了关于 Pixelvalues 的相同信息,从而产生了这 3 张图像。我还尝试了一些我在互联网上找到的数学方程式,但没有一个有效。你能更详细地解释一下你的公式吗?非常感谢您抽出宝贵时间。问候马塞尔 如果你看中间的图像,从左侧中间进入图像朝向汽车,有三个清晰的带从黑色到白色。因此,如果您从黑色开始(值为 0),然后逐渐变为白色(值为 255),您可以看到,当您变为白色时,底部图像会增加 1 级,这就是二进制数相加的方式,所以底部图像是 MSB,顶部图像是下一个最重要的字节,因为当第二个字节达到 255 时,顶部字节点击进入下一个级别。 我已经更新了我的答案 - 请再看看最后一部分。

以上是关于从共享内存中保存 4 字节 pP 深度图像的主要内容,如果未能解决你的问题,请参考以下文章

将函数指针保存在共享内存中

如何在 C++14 中将多字节值写入共享内存?

共享内存实现原理

POSIX 共享内存 - 自动客户端通知的方法

如何直接在boost共享内存中编写opencv cv :: Mat图像

陈天奇:在深度学习框架之间共享张量——内存张量结构DLPack的PythonAPI来了