c++ - 如何处理来自 MIPI 相机的 12 位图像?
问题描述
实际上,我使用的是 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 位连接。jetson 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 这样的库,因为我做了一些具体的过程。我需要处理图像的所有像素,我想知道转换.raw
in是否非常有效unsigned short*
,以使图像适应我的代码。
“包装”从来都不是问题,因为我以前的相机以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);
推荐阅读
- leaflet - 产品的传单提供者,“不是客户的有效来源:”
- android - 返回到 onCreateView 内的上一个片段时,会触发 Button onClick()
- unity3d - 文本到 Unity 中的 2d Lipsync
- amazon-web-services - 是否可以从快照恢复 Redshift 数据库?
- sql - 向主键添加时间戳如何有助于返回更快的搜索结果?
- c++ - 调试为竞争性在线评委编写的程序
- python - 在 Python 中定义和评估可重用的逻辑表达式
- c# - 当整个项目在.NET5中构建“anyCPU”时,是否可以始终以x86运行加载的程序集
- python - 在 Selenium Chrome 驱动程序上无法加载网页并尝试了多年的解决方案,需要新的解决方案
- ios - 共享实例的 AVAudioSession 错误