首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何获取和设置EmguCV Mat图像的像素值?

如何获取和设置EmguCV Mat图像的像素值?
EN

Stack Overflow用户
提问于 2015-08-27 17:04:27
回答 4查看 28K关注 0票数 15

我正在将EmguCV 3.0.0包装器用于OpenCV 3.0库。我在几个地方使用Mat类。下面是一个由double值组成的单通道8x8映像的示例:

代码语言:javascript
运行
复制
Mat image = new Mat(8, 8, DepthType.Cv64F, 1);

Image<>类提供reasonable means for getting and setting pixel values,该方法与Matrix<>类相同,但对于Mat类似乎不那么明显。我知道如何设置单个像素的唯一方法是使用掩码:

代码语言:javascript
运行
复制
// set two pixel values, (0,0) to 9.0, (2, 3) to 42.0

Matrix<byte> mask = new Matrix<byte>(8,8);
mask.Data[0, 0] = 1;
image.SetTo(new MCvScalar(9.0), mask);

mask = new Matrix<byte>(8,8);
mask.Data[2, 3] = 1;
image.SetTo(new MCvScalar(42.0), mask);

这感觉应该是两行,而不是六行,所以我觉得我错过了什么。当Mat不止一个通道时,事情会变得更加复杂,因为Matrix<>仅仅是2D的,所以必须使用掩码在每个通道上设置像素。

我负担不起以这种方式设置像素的时间或内存。如何使用单个方法调用设置像素?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-09-14 07:39:10

通过使用DataPointer复制非托管内存块并将托管类型转换为非托管类型,可以从Mat获取元素。设置值正在相反的方向封送。

例如,可以使用这样的扩展类。

代码语言:javascript
运行
复制
public static class MatExtension
{
    public static dynamic GetValue(this Mat mat, int row, int col)
    {
        var value = CreateElement(mat.Depth);
        Marshal.Copy(mat.DataPointer + (row * mat.Cols + col) * mat.ElementSize, value, 0, 1);
        return value[0];
    }

    public static void SetValue(this Mat mat, int row, int col, dynamic value)
    {
        var target = CreateElement(mat.Depth, value);
        Marshal.Copy(target, 0, mat.DataPointer + (row * mat.Cols + col) * mat.ElementSize, 1);
    }
    private static dynamic CreateElement(DepthType depthType, dynamic value)
    {
        var element = CreateElement(depthType);
        element[0] = value;
        return element;
    }

    private static dynamic CreateElement(DepthType depthType)
    {
        if (depthType == DepthType.Cv8S)
        {
            return new sbyte[1];
        }
        if (depthType == DepthType.Cv8U)
        {
            return new byte[1];
        }
        if (depthType == DepthType.Cv16S)
        {
            return new short[1];
        }
        if (depthType == DepthType.Cv16U)
        {
            return new ushort[1];
        }
        if (depthType == DepthType.Cv32S)
        {
            return new int[1];
        }
        if (depthType == DepthType.Cv32F)
        {
            return new float[1];
        }
        if (depthType == DepthType.Cv64F)
        {
            return new double[1];
        }
        return new float[1];
    }
}

然后,就可以通过单个方法调用获取和设置值。

代码语言:javascript
运行
复制
var row = 2;
var col = 1;
var mat = new Mat(3, 3, DepthType.Cv64F, 3);
mat.SetValue(row, col, 3.14);
var value = mat.GetValue(row, col);

对200000000操作的测试表明,动态类型版本比静态版本慢了~2.5倍。

代码语言:javascript
运行
复制
public static double GetDoubleValue(this Mat mat, int row, int col)
{
    var value = new double[1];
    Marshal.Copy(mat.DataPointer + (row * mat.Cols + col) * mat.ElementSize, value, 0, 1);
    return value[0];
}

public static void SetDoubleValue(this Mat mat, int row, int col, double value)
{
    var target = new[] { value };
    Marshal.Copy(target, 0, mat.DataPointer + (row * mat.Cols + col) * mat.ElementSize, 1);
}
票数 20
EN

Stack Overflow用户

发布于 2017-01-26 16:14:16

基于Bartosz的好答案,我尝试为OpenCvSharp编写它:

代码语言:javascript
运行
复制
    public static dynamic GetValue(this Mat mat, int row, int col)
    {
        var value = CreateElement(mat.Type());
        Marshal.Copy(mat.Data + (row * mat.Cols + col) * mat.ElemSize(), value, 0, 1);
        return value[0];
    }
    public static void SetValue(this Mat mat, int row, int col, dynamic value)
    {
        var target = CreateElement(mat.Type(), value);
        Marshal.Copy(target, 0, mat.Data + (row * mat.Cols + col) * mat.ElemSize(), 1);
    }
    private static dynamic CreateElement(MatType depthType, dynamic value)
    {
        var element = CreateElement(depthType);
        element[0] = value;
        return element;
    }
    private static dynamic CreateElement(MatType depthType)
    {
        switch (depthType)
        {
            case MatType.CV_8S:
                return new sbyte[1];
            case MatType.CV_8U:
                return new byte[1];
            case MatType.CV_16S:
                return new short[1];
            case MatType.CV_16U:
                return new ushort[1];
            case MatType.CV_32S:
                return new int[1];
            case MatType.CV_32F:
                return new float[1];
            case MatType.CV_64F:
                return new double[1];
            default:
                throw new NotImplementedException();
        }
    }
票数 4
EN

Stack Overflow用户

发布于 2021-10-12 08:44:01

一个更好的。

  • 在项目的调试和发行配置中勾选“允许不安全的代码”。
  • 代码:
代码语言:javascript
运行
复制
public static class MatExtension
{
        public static T Get<T>(this Mat mat, int row, int col)
        {
            unsafe
            {
                var span = new ReadOnlySpan<T>(mat.DataPointer.ToPointer(), mat.Rows * mat.Cols * mat.ElementSize);
                return span[row * mat.Cols + col];
            }
        }

        public static ReadOnlySpan<T> Get<T>(this Mat mat, int row, Range cols)
        {
            unsafe
            {
                var span = new ReadOnlySpan<T>(mat.DataPointer.ToPointer(), mat.Rows * mat.Cols * mat.ElementSize);
                var colOffsets = cols.GetOffsetAndLength(span.Length);
                return span.Slice(row * mat.Cols + colOffsets.Offset, colOffsets.Length);
            }
        }
}

用法:

代码语言:javascript
运行
复制
using var stats = new Mat();
using var centroids = new Mat();
//...
var x = stats.Get<int>(i,(int)ConnectedComponentsTypes.Left);
var cxy = centroids.Get<double>(i, 0..1);
double cxy0 = cxy[0];
//...
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32255440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档