如何处理来自MIPI相机的12位图像?

how handle 12-bit image from MIPI camera?

本文关键字:相机 MIPI 12位 图像 何处理 处理      更新时间:2023-10-16

实际上,我使用的是Gige相机。该相机提供unsigned char*图像,这意味着位深度为8。我用 c/c++ 开发。

我将收到一个新的,但那个相机是不同的。这个提供void*,位深度为12。我可以像这样投射void*

unsigned short* img ;
img = (unsigned short*) camera.GetImage() ; /**camera.GetImage() is void*/

这对我来说是新的,我从未使用过原始格式。演员是个好主意吗?我需要访问每个像素,而且我不知道如何处理像素void*.

由于深度,我建议用unsigned short*铸造。相机的像素编码为 12。如果我用unsigned char*投射,我会丢失信息。

感谢您的帮助!

更新

非常感谢您的所有详细信息。由于我是初学者,您的回答对我找到其他调查方法有很大帮助。

我正在研究 jetson TX2,位位置反映了实际硬件。

就我而言,像素数据以 16 位连接。杰森TX2的输出是:

ONE PIXEL
|              16 bits                          |
D5-D4-D3-D2-D1-D0-D11-D10-0-0-D11-D10-D9-D8-D7-D6

我的目标不是显示图像。以下是我的流程说明:

1 - 拍摄5次相同的图像;

2 - 平均图像的计算;

3 - 坏像素校正 ;

4 - 平场校正;

4 - 通过套接字发送最终图像;

在线程中,我获取图像。在另一个线程中,我应用图像处理,在另一个线程中,我通过套接字发送图像。我实现了所有的过程。

我没有使用像openCV这样的库,因为我做了一些特定的过程。我需要处理图像的所有像素,我想知道在unsigned short*中转换.raw是否非常有效,以使图像适应我的代码。

"包装"从来都不是问题,因为我以前的相机在unsigned char*中提供图像。你认为我应该把void*转换成unsigned short*吗?

谢谢你的帮助

您的帖子中没有足够的信息来回答您的问题。 以下是 12 位像素的可能打包:

高效包装


Bit0     Bit11     Bit23      Bit35        Bit47     Bit59     Bit71     Bit83      Bit95
[ Pixel0   | Pixel1  | Pixel2    | Pixel3  | Pixel4   | Pixel5  | Pixel6  |  Pixel7 ]  (that is 8 pixels per 96bits or 3 32-bits word) 

易于使用的包装


Bit0    Bit11     Bit23    Bit32     Bit43     Bit55     Bit63     
[ Pixel0   | Pixel1  | 0    | Pixel3  | Pixel4   | 0      ]  (that is 2 pixels per 32-bits word) 

哑包装


Bit0    Bit11     Bit16    Bit27     Bit31          
[ Pixel0   |  0    | Pixel1  |  0      ]  (that is 1 pixels per 16-bits word) 

您必须阅读相机的数据表才能确定正在使用哪种包装。完成此操作后,您还需要弄清楚用于传输数据字的数据的字节序。例如,在小端系统中,您将首先获得最低有效字节。对于大端系统,您将首先获得最高有效字节。您需要调整像素提取代码以适应机器的字节序。

一旦您弄清楚了位移和遮罩的打包和字节序,提取像素就非常简单。

由于您要求C++解决方案,这里是内存流中的任意位提取器,您需要调整打包和字节序:

struct BitStream
{
const uint8 * begin;
const uint8 * end;
size_t pos;
BitStream(const uint8 * bits, size_t len) : begin(bits), end(bits + len), pos(0) {}
// get value from bitstream coded on len bits
uint32 get(uint8 len)
{
size_t byte_offset = pos/8;
uint8 bit_pos = pos % 8;
uint8 bit_avail = 8 - bit_pos;
if (begin+byte_offset >= end) return 0;
if (bit_avail >= len)
{
uint32 value = begin[byte_offset];
uint8 mask = ~(0xff << len) << bit_pos;
value = value & mask;
value = value >> bit_pos;
pos = pos + len;
return value;
}
else
{
uint32 value = get(bit_avail);
value = value | (get(len - bit_avail)<<bit_avail);
return value;
}
}
void skip(uint8 len) { pos += len; }
bool done() const { return (begin + pos/8) >= end; }
};

如果相机和机器之间存在字节序不匹配,则需要像这样交换返回的像素:

BitStream bs((const uint8*)camera.getImage(), camera.getImageLen());
// Get pixel
uint16 pixel = (uint16)bs.get(12);
// Comment the line below if the endianness is the same
pixel = ((pixel & 0xFF00) >> 8) | (pixel << 8);
// Skip the stuffing zero bits depending on packing format, here I assume dumb packing
bs.skip(4); 

感谢您更新您的问题。

如果像现在看起来的那样,每个 12 位像素都完全包含在带有 4 位填充的 16 位无符号短时间内,那么"是"无符号短绝对是要走的路。我不知道你的环境是否有uint16_t,但可以保证正好是 16 位(我觉得更好(,而unsigned short">至少">是 16 位。

现在你只需要做一些AND和转移...