如何在C#中为EmguCV的Mat逐像素赋值?
嘿,我之前也纠结过这个问题,现在给你分享几种用Emgu CV的Mat类逐像素赋值的实用方法,亲测有效:
方法1:使用
Mat.At<T>()方法(最直观易读) 这是最常用的方式,Emgu CV为Mat提供了泛型的At<T>方法,你只需要根据Mat的像素类型传入对应的泛型参数就行:
示例1:8位单通道灰度图
// 创建一个200x200的8位单通道灰度Mat Mat grayMat = new Mat(200, 200, DepthType.Cv8U, 1); // 双层循环逐像素赋值 for (int y = 0; y < grayMat.Rows; y++) { for (int x = 0; x < grayMat.Cols; x++) { // 这里可以根据x、y自定义像素值,比如生成渐变效果 byte pixelValue = (byte)((x + y) % 256); // 注意坐标是(y, x):先行后列,别搞反! grayMat.At<byte>(y, x) = pixelValue; } }
示例2:3通道彩色图(BGR格式)
Emgu CV默认用BGR顺序,所以可以直接用Bgr结构:
// 创建一个100x100的3通道彩色Mat Mat colorMat = new Mat(100, 100, DepthType.Cv8U, 3); for (int y = 0; y < colorMat.Rows; y++) { for (int x = 0; x < colorMat.Cols; x++) { // 直接赋值BGR颜色,比如纯红色 colorMat.At<Bgr>(y, x) = new Bgr(0, 0, 255); // 如果需要单独修改某一通道,也可以这样操作: // var currentColor = colorMat.At<Bgr>(y, x); // currentColor.Green = 255; // 改成绿色 // colorMat.At<Bgr>(y, x) = currentColor; } }
方法2:直接操作Data指针(性能最优,适合大数据量)
如果你的图像尺寸很大,At<T>方法的调用开销会累积,这时候直接操作内存指针会快很多。不过要注意开启项目的不安全代码支持:
Mat grayMat = new Mat(500, 500, DepthType.Cv8U, 1); // 锁定Mat的内存并获取指针,用using确保内存正确释放 using (var dataPtr = grayMat.GetDataPointer()) { int stride = grayMat.Step; // 每行的字节数(步长) unsafe { byte* basePtr = (byte*)dataPtr; for (int y = 0; y < grayMat.Rows; y++) { // 获取当前行的起始指针 byte* rowPtr = basePtr + y * stride; for (int x = 0; x < grayMat.Cols; x++) { rowPtr[x] = (byte)((x * y) % 256); } } } }
方法3:通过数组+
SetData批量赋值 如果可以先把所有像素值存入数组,再一次性写入Mat,这种方式也很方便:
int width = 300; int height = 300; Mat grayMat = new Mat(height, width, DepthType.Cv8U, 1); // 创建对应大小的像素数组 byte[] pixelArray = new byte[width * height]; // 先给数组赋值 for (int i = 0; i < pixelArray.Length; i++) { int y = i / width; int x = i % width; pixelArray[i] = (byte)((x - y) % 256); } // 把数组数据写入Mat grayMat.SetData(pixelArray);
关键注意事项
- 必须匹配像素类型:比如8位单通道用
byte,16位单通道用ushort,32位浮点用float;彩色通道对应Bgr、Rgb等Emgu CV提供的颜色结构。 - 坐标顺序是**(y, x)**:也就是先访问行,再访问列,搞反的话图像会出现奇怪的变形。
- 指针操作需要开启不安全代码:右键项目→属性→生成→勾选"允许不安全代码"。
内容的提问来源于stack exchange,提问作者user9733371
相关产品推荐
相关产品推荐

