You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决cv::Mat宽度非4倍数时在PictureBox显示的异常问题

解决24位RGB格式cv::Mat显示到PictureBox时的步长对齐问题

问题根源

Windows的Bitmap要求每行像素数据的字节数(即stride/步长)必须是4的倍数,而OpenCV的cv::Mat在24位RGB格式下,若列数cols不是4的倍数,其默认步长为cols*3,不满足4的倍数要求。直接修改步长会导致内存缓冲区长度不匹配,触发System.AccessViolationException。

解决方案:使用Bitmap.LockBits逐行复制数据

通过LockBits获取Bitmap的缓冲区,逐行将cv::Mat的有效像素数据复制到Bitmap的对齐缓冲区中,既满足步长要求,又避免内存访问越界。

完整代码示例(C++/CLI)

// 确保matSrc是24位RGB格式(OpenCV默认是BGR,需先转换)
cv::cvtColor(matSrc, matSrc, cv::COLOR_BGR2RGB);

// 创建对应尺寸的24位RGB Bitmap
System::Drawing::Bitmap^ bmp = gcnew System::Drawing::Bitmap(
    matSrc.cols, 
    matSrc.rows, 
    System::Drawing::Imaging::PixelFormat::Format24bppRgb
);

// 锁定Bitmap缓冲区以写入数据
System::Drawing::Imaging::BitmapData^ bmpData = bmp->LockBits(
    System::Drawing::Rectangle(0, 0, bmp->Width, bmp->Height),
    System::Drawing::Imaging::ImageLockMode::WriteOnly,
    bmp->PixelFormat
);

unsigned char* srcPtr = matSrc.data;
unsigned char* dstPtr = static_cast<unsigned char*>(bmpData->Scan0);
int srcStride = matSrc.step;    // 原Mat的步长
int dstStride = bmpData->Stride;// Bitmap对齐后的步长

// 逐行复制像素数据
for (int i = 0; i < matSrc.rows; ++i) {
    // 复制一行的有效RGB数据(共cols*3字节)
    memcpy(dstPtr, srcPtr, matSrc.cols * 3);
    // 移动到下一行的起始地址
    srcPtr += srcStride;
    dstPtr += dstStride;
}

// 解锁缓冲区
bmp->UnlockBits(bmpData);

// 显示到PictureBox
pictureBox1->Image = bmp;

关键说明

  1. 颜色格式转换:OpenCV读取的图像默认是BGR格式,必须先通过cv::COLOR_BGR2RGB转换为RGB,否则显示颜色会反转。
  2. 逐行复制:Bitmap的对齐步长可能大于cols*3,复制时仅需覆盖每行的有效像素区域,剩余填充字节无需处理,不影响显示效果。
  3. 内存安全:通过LockBits操作缓冲区,避免直接修改步长导致的内存越界,完全符合Windows位图的内存规范。

内容的提问来源于stack exchange,提问作者user727062

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 12:17:25