OpenCvSharp:MatType与C#数据类型对应关系

文章介绍了在使用OpenCvSharp进行图像处理时,如何正确匹配MatType和C#数据类型以避免像素值错误。提供了一个MatType和C#类型的数据对照表,包括不同位数、数据类型和通道数的组合,并展示了错误类型匹配可能导致的后果。此外,还给出了一个TypeMap属性的示例,用于快速查找和转换类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的

在使用OpenCvSharp过程中,经常需要访问或修改像素值(如At),使用正确的C#数据类型与MatType对应,否则会导致获取或修改的像素值有误,因此,做了个类型做对照表,方便日后查找。

MatType类型

格式:CV_[位数][数据类型]C[通道数]

如:MatType.CV_8UC3 表示3通道8位无符号整数

       MatType.CV_64FC4 表示4通道64位浮点数

位数:8位、16位、32位、64位

数据类型:S(Signed integer)有符号整数、U(Unsigned integer)无符号整数、F(Float) 浮点数

通道数:1、2、3、4等(大于0,小于512)

MatType类型C#数据类型对照表

对照表
类型数据类型对应C#类型取值范围
CV_8U8位无符号整数byte0到255
CV_8S        8位带符号整数sbyte-128到127
CV_16U16位无符号整数

ushort

char

0到65,535
CV_16S16位带符号整数short-32,768 到 32,767
CV_32S32位带符号整数  int-2,147,483,648 到 2,147,483,647
CV_32F32位浮点数float±1.5 x 10^−45 至 ±3.4 x 10^38
CV_64F64位浮点数double±5.0 × 10^−324 到 ±1.7 × 10^308
CV_USERTYPE1自定义

 MatType的TypeMap属性

/// <summary>
/// typeof(T) -> MatType
/// </summary>
protected static readonly IReadOnlyDictionary<Type, MatType> TypeMap = new Dictionary<Type, MatType>
    {
        [typeof(byte)] = MatType.CV_8UC1,
        [typeof(sbyte)] = MatType.CV_8SC1,
        [typeof(short)] = MatType.CV_16SC1,
        [typeof(char)] = MatType.CV_16UC1,
        [typeof(ushort)] = MatType.CV_16UC1,
        [typeof(int)] = MatType.CV_32SC1,
        [typeof(float)] = MatType.CV_32FC1,
        [typeof(double)] = MatType.CV_64FC1,

        [typeof(Vec2b)] = MatType.CV_8UC2,
        [typeof(Vec3b)] = MatType.CV_8UC3,
        [typeof(Vec4b)] = MatType.CV_8UC4,
        [typeof(Vec6b)] = MatType.CV_8UC(6),

        [typeof(Vec2s)] = MatType.CV_16SC2,
        [typeof(Vec3s)] = MatType.CV_16SC3,
        [typeof(Vec4s)] = MatType.CV_16SC4,
        [typeof(Vec6s)] = MatType.CV_16SC(6),

        [typeof(Vec2w)] = MatType.CV_16UC2,
        [typeof(Vec3w)] = MatType.CV_16UC3,
        [typeof(Vec4w)] = MatType.CV_16UC4,
        [typeof(Vec6w)] = MatType.CV_16UC(6),

        [typeof(Vec2i)] = MatType.CV_32SC2,
        [typeof(Vec3i)] = MatType.CV_32SC3,
        [typeof(Vec4i)] = MatType.CV_32SC4,
        [typeof(Vec6i)] = MatType.CV_32SC(6),

        [typeof(Vec2f)] = MatType.CV_32FC2,
        [typeof(Vec3f)] = MatType.CV_32FC3,
        [typeof(Vec4f)] = MatType.CV_32FC4,
        [typeof(Vec6f)] = MatType.CV_32FC(6),

        [typeof(Vec2d)] = MatType.CV_64FC2,
        [typeof(Vec3d)] = MatType.CV_64FC3,
        [typeof(Vec4d)] = MatType.CV_64FC4,
        [typeof(Vec6d)] = MatType.CV_64FC(6),

        [typeof(Point)] = MatType.CV_32SC2,
        [typeof(Point2f)] = MatType.CV_32FC2,
        [typeof(Point2d)] = MatType.CV_64FC2,

        [typeof(Point3i)] = MatType.CV_32SC3,
        [typeof(Point3f)] = MatType.CV_32FC3,
        [typeof(Point3d)] = MatType.CV_64FC3,

        [typeof(Size)] = MatType.CV_32SC2,
        [typeof(Size2f)] = MatType.CV_32FC2,
        [typeof(Size2d)] = MatType.CV_64FC2,

        [typeof(Rect)] = MatType.CV_32SC4,
        [typeof(Rect2f)] = MatType.CV_32FC4,
        [typeof(Rect2d)] = MatType.CV_64FC4,

        [typeof(DMatch)] = MatType.CV_32FC4,
    };

源码示例

Mat mat1 = Mat.Ones(new Size(3, 3), MatType.CV_8U);
//正确结果  1
Console.WriteLine(mat1.At<byte>(0, 0));
//错误结果  16843009
Console.WriteLine(mat1.At<int>(0, 0));


Mat mat2 = new Mat(3, 3, MatType.CV_8S, new sbyte[]{-4,-3,-2,
                                                    -1,0,1,
                                                    2,3,4});

//正确结果  -3
Console.WriteLine(mat2.At<sbyte>(0, 1));
//错误结果  253
Console.WriteLine(mat2.At<byte>(0, 1));
//错误结果  16776957
Console.WriteLine(mat2.At<int>(0, 1));

//错误的初始化
//类型int与MatType.CV_8U不对应
Mat mat3 = new Mat(3, 3, MatType.CV_8U, new int[] {1,2,3,
                                                   4,5,6,
                                                   7,8,9});
//实际mat3内容
//1,   0,   0
//0,   2,   0
//0,   0,   3

//想得到2,实际是0
Console.WriteLine(mat3.At<byte>(0, 1));
### 如何在 OpenCVOpencvSharp 之间传递数据或对象 #### 数据结构差异 OpenCV 使用 `cv::Mat` 对象表示图像矩阵,而 OpencvSharp对应的类是 `Mat`。两者虽然名称相同但在不同编程环境中实现细节有所区别[^1]。 #### BitmapData 导致的问题 当尝试将 C# 的 `Bitmap` 转换为 OpenCV 的 `Mat` 或者反过来时,可能会遇到由于 `BitmapData` 处理不当造成的图片扭曲问题。这通常是因为扫描行字节对齐方式不一致引起的。为了防止这种情况发生,在转换过程中应当特别注意步幅(stride)以及颜色通道排列顺序。 #### 解决方案:互转方法 对于从 C# 到 C++ (即 OpencvSharp 至原生 OpenCV),可以通过共享内存的方式来进行高效的数据交换: - **C#端**:创建托管数组并将它固定到非移动位置;接着调用 P/Invoke 函数向未管理代码暴露指针。 ```csharp // 假设 img 是一个 Mat 类型的对象 IntPtr ptr = img.Ptr; unsafe { byte* p = (byte*)ptr.ToPointer(); } ``` - **C++端**:接收来自 C# 的裸指针作为输入参数构建新的 `cv::Mat` 实例 ```cpp extern "C" __declspec(dllexport) void ProcessImage(unsigned char* data, int width, int height, int channels){ cv::Mat mat(height, width, CV_8UC(channels), data); // 进行必要的处理... } ``` 相反方向上,则需先准备好 C++ 端的 `cv::Mat` 并将其原始像素访问权限授予给 C#: ```cpp void GetImageData(cv::Mat& src, unsigned char*& dst, size_t &size){ size = src.total() * src.elemSize(); dst = new unsigned char[size]; memcpy(dst, src.datastart, size); } // 需要在适当时候释放分配出去的空间 delete[] dst; ``` 之后可以在 C# 中重新构造 `Mat` : ```csharp using(var mat = new Mat(rows, cols, type)){ Marshal.Copy(dataPtr, bufferArray, 0, bufferSize); Cv2.ImDecode(bufferArray, ImreadModes.Color); // 如果是从编码后的流读取的话 } ``` 以上过程确保了两个库间能够安全有效地传输图像信息而不丢失任何重要属性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图南科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值