图像处理中Stride方法理解

什么是Image Stride? 当视频图像存储在内存中时,内存缓冲区可能在每行像素后包含额外的填充字节。填充字节会影响图像在内存中的存储方式,但不会影响图像的显示方式。)在本例中,函数为目标图像中的三个平面保留三个单独的指针。有关计算图像Stride和使用视频媒体缓冲区的更多信息,请参阅未压缩的视频缓冲区。如果存在填充字节,则**Stride **比图像的宽度宽,如下图所示。此外,有两种方式可以将图像排列在存储器中。在自上而下的图像中,图像中最上面的一行像素首先出现在内存中。,并且Direct3D曲面中包含的任何图像都必须是自上而下的。 阅读详情
AI摘要

本文深入探讨了图像处理中Stride的概念,特别是在BitmapData类中如何处理图像数据。详细解释了Stride是如何根据图像宽度和像素位数计算的,以及为何需要进行4字节对齐。

一行有 11 个像素(Width = 11), 对一个 32 位(每个像素 4 字节)的图像, Stride = 11 * 4 = 44.

但还有个字节对齐的问题, 譬如:

一行有 11 个像素(Width = 11), 对一个 24 位(每个像素 3 字节)的图像, Stride = 11 * 3 + 3 = 36.

为什么不是 Stride = 33? 因为它是按 4 字节对齐的.

根据上面道理, 我们可以手动计算 Stride 的值:

1、Stride = 每像素占用的字节数(也就是像素位数/8) * Width;

2、如果 Stride 不是 4 的倍数, 那么 Stride = Stride + (4 - Stride mod 4);

下面的例子测试和验证了上面的思路:

uses GdiPlus; 
 
procedure TForm1.FormPaint(Sender: TObject); 
var 
 Bitmap: IGPBitmap; 
 Rect: TGPRect; 
 Graphics: IGPGraphics; 
 Data: TGPBitmapData; 
 n: Integer; 
begin 
 ChDir('C:\GdiPlusImg\'); 
 Bitmap := TGPBitmap.Create('Grapes.jpg'); 
 Rect.Initialize(0, 0, Bitmap.Width, Bitmap.Height); 
 Data := Bitmap.LockBits(Rect, [ImageLockModeRead], Bitmap.PixelFormat); 
 n := GetPixelFormatSize(Data.PixelFormat) div 8 * Data.Width; 
 n := n + (4 - n mod 4); 
 ShowMessageFmt('%d, %d, %d', [Data.Width, Data.Stride, n]); { 187, 564, 564 } 
 Bitmap.UnlockBits(Data); 
 
 // 
 Bitmap := TGPBitmap.Create('Bird.bmp'); 
 Rect.Initialize(0, 0, Bitmap.Width, Bitmap.Height); 
 Data := Bitmap.LockBits(Rect, [ImageLockModeRead], Bitmap.PixelFormat); 
 n := GetPixelFormatSize(Data.PixelFormat) div 8 * Data.Width; 
 if n mod 4 <> 0 then n := n + (4 - n mod 4); 
 ShowMessageFmt('%d, %d, %d', [Data.Width, Data.Stride, n]); { 110, 112, 112 } 
 Bitmap.UnlockBits(Data); 
 
 // 
 Bitmap := TGPBitmap.Create('Apple.gif'); 
 Rect.Initialize(0, 0, Bitmap.Width, Bitmap.Height); 
 Data := Bitmap.LockBits(Rect, [ImageLockModeRead], Bitmap.PixelFormat); 
 n := GetPixelFormatSize(Data.PixelFormat) div 8 * Data.Width; 
 if n mod 4 <> 0 then n := n + (4 - n mod 4); 
 ShowMessageFmt('%d, %d, %d', [Data.Width, Data.Stride, n]); { 120, 120, 120 } 
 Bitmap.UnlockBits(Data); 
 
 // 
 Bitmap := TGPBitmap.Create('ImageFileSmall.jpg'); 
 Rect.Initialize(0, 0, Bitmap.Width, Bitmap.Height); 
 Data := Bitmap.LockBits(Rect, [ImageLockModeRead], Bitmap.PixelFormat); 
 n := GetPixelFormatSize(Data.PixelFormat) div 8 * Data.Width; 
 if n mod 4 <> 0 then n := n + (4 - n mod 4); 
 ShowMessageFmt('%d, %d, %d', [Data.Width, Data.Stride, n]); { 320, 960, 960 } 
 Bitmap.UnlockBits(Data); 
end; 

图像处理中的跨度(stride)

使用C#的BitmapData

最近要转开发平台,正研究C#。C#好是好,不过处理图片时一个像素一个像素的操作像素不是一般的慢。其实Delphi也一样,但好在Delphi的Bitmap类提供了ScanLines,可以一行一行的读图,效率比较高。C#应该也有类似的东东。经过一番搜索,终于发现了BitmapData类。

先看个例子,这是对一张位图的每个像素按FF取补,然后输出到一个新图(代码有点啰嗦,不过应该可以说明问题了)。

int h = m_Bmp.Height;
int w = m_Bmp.Width;

Bitmap bmpOut = new Bitmap(w, h, PixelFormat.Format24bppRgb);

BitmapData dataIn = m_Bmp.LockBits(new Rectangle(0,0,w,h),ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb;
BitmapData dataOut = bmpOut.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe
{
byte* pIn = (byte*)(dataIn.Scan0.ToPointer());
byte * pOut = (byte*)(dataOut.Scan0.ToPointer());

for (int y = 0; y < dataIn.Height; y++)
{
for (int x = 0; x < dataIn.Width; x++)
{

pOut[0] = (byte)(255 - pIn[0]);
pOut[1] = (byte)(255 - pIn[1]);
pOut[2] = (byte)(255 - pIn[2]);

pIn += 3;
pOut += 3;
}

pIn += dataIn.Stride - dataIn.Width * 3;
pOut += dataOut.Stride - dataOut.Width * 3;
}
}

bmpOut.UnlockBits(dataOut);
m_Bmp.UnlockBits(dataIn);

貌似比Delphi复杂得多,难道我真的天生对指针过敏?还是Delphi的比较好理解,就是扫描每一行,然后对当前像素点的三个分量做处理,非常方便。而且C#代码中的Stride是个什么东东?

查找了不少资料,现在我是这么理解的:

假设有一张图片宽度为6,因为是Format24bppRgb格式(每像素3字节。在以下的讨论中,除非特别说明,否则Bitmap都被认为是24位RGB)的,显然,每一行需要6*3=18个字节存储。对于Bitmap就是如此。但对于BitmapData,虽然BitmapData.Width还是等于Bitmap.Width,但大概是出于显示性能的考虑,每行的实际的字节数将变成大于等于它的那个离它最近的4的整倍数,此时的实际字节数就是Stride。就此例而言,18不是4的整倍数,而比18大的离18最近的4的倍数是20,所以这个BitmapData.Stride = 20。显然,当宽度本身就是4的倍数时,BitmapData.Stride = Bitmap.Width * 3。

画个图可能更好理解。R、G、B 分别代表3个原色分量字节,BGR就表示一个像素。为了看起来方便我在每个像素之间插了个空格,实际上是没有的。X表示补足4的倍数而自动插入的字节。为了符合人类的阅读习惯我分行了,其实在计算机内存中应该看成连续的一大段。

Scan0
|
|———Stride—————–|
|———Width————-| | 注:Width是图片(BGR作为一个单位)宽度
BGR BGR BGR BGR BGR BGR XX
BGR BGR BGR BGR BGR BGR XX
.
.
.

现在应该很好理解了。首先用 BitmapData.Scan0找到第0个像素的第0个分量的地址。这个地址指向的是个byte类型,所以当时定义为byte* pIn。
行扫描时,在当前指针位置(不妨看成当前像素的第0个颜色分量)连续取出三个值(3个原色分量。注意,0 1 2代表的次序是B G R。在取指针指向的值时,貌似p[n]和p += n再取p[0]是等价的),然后下移3个位置(pIn += 3,看成指到下一个像素的第0个颜色分量)。做过Bitmap.Width次操作后,就到达了Bitmap.Width * 3的位置,应该要跳过图中标记为X的字节了(共有Stride - Width * 3个字节),代码中就是 pIn += dataIn.Stride - dataIn.Width * 3;

跳过以后指针就到达下行的第0个像素了。按照此算法,一共需要做Bitmap.Height次行扫描(代码就是 for (int y = 0; y < dataIn.Height; y++))。

另外,因为使用了unsafe,所以编译的时候需要设置“允许不安全的代码”。

解析内存图像行跨度:Stride 解析内存图像行跨度:Stride Stride的来由 我们都知道现在计算机的cpu都是32位或者64位的cpu,他们一次最少读取4、8个字节,如果少于这些,反而要做一些额外的工作,会花更长的时间。所有会有一个概念叫做内存对齐,将结构体的长度设为4、8的倍数。Stride也是因为同样的理由出现的。因为图像的操作通常按行操作的,如果图像的所有数据都紧密排列,那么会发生非常多次的读取非对齐内存,从而影响效率。而图像的处理本就是一个分秒必争的操作,所以为了性能的提高就引入了Stride这个概念。 Stride的含义 阅读详情

相关推荐

图像格式中的 stride 和 pix stide

Stride:每行图像数据在内存中占用的字节数,可能包括填充。Pix Stride:每个像素在内存中占用的字节数,通常与色彩深度相关。

靑い空゛ 1044

图像中stride的含义

image stride(图像行跨度) 即内存中每行像素所占的控件,为了实现内存对齐或者其他的原因,每行像素在内存中所占据的空间并不是图像的宽度。 如图所示,对于图像数据而言,其像素存储是一行接一行的,但是对于不同的图像格式可能采用不同的压缩方式,而这些压缩方式的数据也需要存储到图像中,方便读取以及写入。在上图中,图像中的height就是图像的高,而图像的宽不是一行数据的大小,而只是其中的一部分数据。stride是width以及 padding的和。width即使图像的框,而padding则用来存贮与

yh13572438258的博客 5642

嵌入式图像处理中的 Stride 原理与 Rockchip 平台对齐实践

Stride 是图像内存布局中连接硬件访问与软件视图的关键参数,本质是单行像素在内存中占用的字节数,受总线对齐、Cache 行和硬件加速器微架构共同约束。其核心原理在于:为保障 DMA 突发传输效率与数据完整性,Stride 必须满足特定字节或像素对齐要求(如 Rockchip 平台强制 16 像素对齐),而非简单等于图像宽度乘以每像素字节数。这一机制直接决定 ISP、VPU、显示控制器等模块能否正确解析帧缓冲区,规避花屏、条纹等典型异常。在实际工程中,它广泛应用于 RK1126/RK3566 等 SoC

weixin_32869687的博客 427

图像stride含义以及对齐原因

图像 stride

C++的知识 1982

从零到一:用AXI DataMover在Zynq MPSoC上实现高效DMA传输(附Vitis HLS驱动示例)

本文详细介绍了如何在Xilinx Zynq UltraScale+ MPSoC平台上使用AXI DataMover实现高效的DMA数据传输。通过解析AXI DataMover架构、Vivado工程配置、Vitis HLS驱动开发及性能优化技巧,帮助开发者快速构建高性能数据传输通道,并提供了可直接复用的代码示例。

weixin_42520796的博客 423

Ubuntu20.04安装NVIDIA显卡驱动避坑指南:从.run文件到完美运行

本文详细介绍了在Ubuntu20.04系统上通过.run文件安装NVIDIA显卡驱动的完整流程和避坑技巧。从禁用Nouveau驱动、选择合适显示管理器到处理常见安装问题,提供了一套经过验证的解决方案,帮助用户顺利完成驱动安装并优化性能。

weixin_30776273的博客 602

Bitmap类getPixels()方法中参数stride理解

http://ranlic.iteye.com/blog/1313735

hsstc的专栏 737

VGA系列之一:VGA显示网络图片

VGA系列之一:VGA显示网络图片VGA系列之一VGA显示网络图片 1 如何用FPGA实现VGA显示 2 网络图片和VGA显示有何区别 3VGA如何显示图片

善良の一休君的博客 1万+

【高通平台 stride计算】

stride 计算

pgDegloveandroid的博客 750

python sci sci-hub 爬论文

sci-hub 爬虫 后续加入对于时间的排序,下载最新文献 参考: https://www.guanjihuan.com/archives/6846 https://blog.youkuaiyun.com/czh2637750821/article/details/115508922

weixin_42783619的博客 3541

香橙派R1 Plus LTS变身无线AP/客户端:手把手教你用RTL8811CU和MT7601U网卡刷OpenWRT

本文详细介绍了如何将香橙派R1 Plus LTS开发板通过RTL8811CU和MT7601U两款USB无线网卡刷入OpenWRT系统,实现无线AP热点发射与客户端接入的双重功能。从硬件选型、驱动安装到双网卡协同配置,提供完整的实战指南,帮助用户快速搭建稳定高效的无线网络解决方案。

weixin_30919429的博客 408

人工智能-Pytorch案例实战(2)-CNN 的stride和zero-padding

CNN 的stride stride:是filter 滑动图像的步长 例如: stride = 1 ,对于一个7 * 7 的灰白图片,通过一个3 * 3 大小的filter,输出下一个图片的大小为5 * 5 (如何计算呢?公式呢?) (W-F+2P/S) + 1 = (7 - 3 + 0)/1 + 1 = 5 stride = 2 ,对于一个7 * 7 的灰白图片,通过一个3 * 3 大小的f...

艾文 1502

高效爬取懂车帝车型数据:从静态解析到动态反爬实战

本文详细解析了如何高效爬取懂车帝车型数据,从静态HTML解析到动态接口反爬的完整实战路径。文章重点介绍了使用浏览器开发者工具定位数据、应对CSS混淆与参数加密等反爬策略,并提供了整合静态与动态抓取逻辑的Python代码示例,帮助开发者稳健地获取结构化车型信息。

wind6的博客 935

用NumPy手写卷积:滑窗循环与im2col矩阵乘法实现全解析

卷积是深度学习和图像处理中最基础也最核心的运算之一。很多人在理解卷积公式后,真正动手用NumPy实现时却常被padding、stride、输出尺寸推导等细节困住。本文从最直观的滑窗循环讲起,逐步过渡到高效矩阵乘法(im2col思路),并对比两种实现的适用场景和性能差异。在图像滤波、边缘检测等工程实践中,掌握这两种实现不仅有助于验证算法原理,还能与PyTorch、TensorFlow等框架的前向计算对拍,深入理解底层数据流动。文章同时梳理了卷积核是否需要翻转、边界补齐模式、内存爆炸等常见坑点,为资深开发者提供

weixin_28221501的博客 235

DA14531之搭建开发环境

DA14531之搭建开发环境

hejinwu1314的博客 1776

基于嵌入式Linux设计的智能车库(GEC6818)

随着城市化进程的加快,传统停车管理方式存在效率低下、人工成本高、车主体验差等问题。为解决这些问题,本项目基于嵌入式Linux技术,设计并实现了一套智能车库管理系统。该系统采用GEC6818开发板作为核心控制器,运行Qt应用程序,并结合USB免驱摄像头进行车牌识别,RFID模块完成刷卡支付,SQLite数据库存储车主信息和停车记录。系统提供车主注册、用户管理、出入库管理、停车费结算、车辆查询等功能,并具备语音播报提示,提高用户体验。通过本系统,停车场管理更加高效、智能,有助于提升停车服务质量,减少人工干预,适

441

图像处理中Stride的理解

一行有 11 个像素(Width = 11), 对一个 32 位(每个像素 4 字节)的图像, Stride = 11 * 4 = 44.   但还有个字节对齐的问题, 譬如:   一行有 11 个像素(Width = 11), 对一个 24 位(每个像素 3 字节)的图像, Stride = 11 * 3 + 3 = 36.   为什么不是 Stride = 33? 因为它是按

小向的专栏 2万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

图像处理中的跨度(stride)

原文:图像处理中的跨度(stride) 使用C#的BitmapData 最近要转开发平台,正研究C#。C#好是好,不过处理图片时一个像素一个像素的操作像素不是一般的慢。其实Delphi也一样,但好在Delphi的Bitmap类提供了ScanLines,可以一行一行的读图,效率比较高。...

weixin_34405557的博客 1851

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

深度学习基础--Stride的理解

Stride的理解   stride其实是图像处理中常用的概念。 解释   一行有 11 个像素(Width = 11), 对一个 32 位(每个像素 4 字节)的图像, Stride = 11 * 4 = 44.   但还有个字节对齐的问题, 譬如:   一行有 11 个像素(Width = 11), 对一个 24 位(每个像素 3 字节)的图像, Stride = 11 * 3 + 3 = 3...

wydbyxr的博客 3万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【转】图像处理中Stride的理解

一行有 11 个像素(Width = 11), 对一个 32 位(每个像素 4 字节)的图像, Stride = 11 * 4 = 44. 但还有个字节对齐的问题, 譬如: 一行有 11 个像素(Width = 11), 对一个 24 位(每个像素 3 字节)的图像, Stride = 11 * 3 + 3 = 36. 为什么不是 Stride = 33? 因为它是按 4 字节对齐的. 根据上面道理, 我们可以手动计算 Stride 的值: 1、Stride = 每像素占用的字节数(也就是像素位数/8) *

lgfun的专栏 1101
上一篇: 无法从带有索引像素格式的图像创建 Graphics 对象
下一篇: 彩色图像、灰度图像、二值图像和索引图像区别
.NET跨平台
博客等级 码龄15年 6066粉丝 738原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值