【VM服务管家】专题_7.3 图像转换

3.1 图像转换扫盲篇(CSharp)

描述
环境:VM4.2 + VS2013及以上
现象:相机、VM脚本、VM SDK、算子SDK、算法模块中的图像类型是什么?
解答

  1. 图像格式一览
    除了Bitmap、Mat和Halcon中的图像类型,在VM和开发(开发包含三种:VM SDK开发(也称VM二次开发)算子SDK开发、自定义算法模块开发)中涉及的图像类型如下:
    相机:图像数据流(此处图像数据流类型是MyCamera.MV_FRAME_OUT,是来自MvCameraControl.Net.dll,即海康机器人工业相机SDK,在MVS SDK和算子SDK中都有这个dll;算子SDK的MVDCamera.Net.dll也可以进行相机取流,它是对MvCameraControl.Net.dll的二次封装,用MVDCamera.Net.dll时,图像数据流类型是CMvdImage);
    VM:脚本输入图像(图像类型是ImageData);
    VM SDK:流程输入图像(ImageBaseData_V2,VM4.2 SDK新增)、Group输入图像(ImageBaseData_V2,VM4.2 SDK新增)、图像源SDK输入图像(ImageBaseData)、模块输入图像(InputImageData)、流程输出图像(区分VM4.0 SDK和VM4.2 SDK的获取输出图像的方式,VM4.2获取流程图像的类型是ImageBaseData_V2) ;
    算子SDK:输入图像(CMvdImage);
    算法模块:输入图像(HKA_IMAGE,是C++中图像类型)。
  2. 图像类型转换(含单通道和三通道图像)三通道的Bitmap、Mat为BGR,三通道的VM和二次开发为RGB,针对常用图像转换场景,列举如下(见3.2~3.6)。篇幅所致,后续每种图像转换用函数表达,函数输入某种图像类型,返回转换后的某种图像类型。

3.2 相机采图转流程输入、Group输入、图像源SDK输入、模块输入、算子输入图像

描述
环境:VM4.2 + VS2013及以上
现象:相机采图转换成其他图像类型
解答
相机采图(MyCamera.MV_FRAME_OUT)转换为流程输入图像、Group输入图像、图像源SDK输入图像、模块输入图像、算子输入图像。
1 相机采图转流程输入(ImageBaseData_V2)、Group输入(ImageBaseData_V2)

public ImageBaseData_V2 CCDToImageBaseDataV2(MyCamera.MV_FRAME_OUT frameOut)
{
    ImageBaseData_V2 imageBaseDataV2 = new ImageBaseData_V2();
    if (frameOut.stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
    {
        imageBaseDataV2 = new ImageBaseData_V2(frameOut.pBufAddr, frameOut.stFrameInfo.nFrameLen, frameOut.stFrameInfo.nWidth, frameOut.stFrameInfo.nHeight, VMPixelFormat.VM_PIXEL_MONO_08);
    }
    else if (frameOut.stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
    {
        imageBaseDataV2 = new ImageBaseData_V2(frameOut.pBufAddr, frameOut.stFrameInfo.nFrameLen, frameOut.stFrameInfo.nWidth, frameOut.stFrameInfo.nHeight, VMPixelFormat.VM_PIXEL_RGB24_C3);
    }

    return imageBaseDataV2;
}
var image = CCDToImageBaseDataV2(stFrameOut);
//设置到流程
var procedure = VmSolution.Instance["流程1"] as VmProcedure;
procedure.ModuParams.SetInputImage_V2("ImageData", image);
//设置到Group
var group = VmSolution.Instance["流程1.组合模块1"] as IMVSGroupTool;
group.ModuParams.SetInputImage_V2("ImageData", image);

2 相机采图转图像源SDK输入(ImageBaseData)

public ImageBaseData CCDToImageBaseData(MyCamera.MV_FRAME_OUT frameOut)
{
    ImageBaseData imageBaseData = new ImageBaseData();
    imageBaseData.Width = frameOut.stFrameInfo.nWidth;
    imageBaseData.Height = frameOut.stFrameInfo.nHeight;
    imageBaseData.DataLen = frameOut.stFrameInfo.nFrameLen;
    if (frameOut.stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
    {
        imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_MONO_08;
    }
    else if (frameOut.stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
    {
        imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_RGB24_C3;
    }
    imageBaseData.ImageData = new byte[frameOut.stFrameInfo.nFrameLen];
    Marshal.Copy(frameOut.pBufAddr, imageBaseData.ImageData, 0, (int)frameOut.stFrameInfo.nFrameLen);
    return imageBaseData;
}
var image = CCDToImageBaseData(stFrameOut);
//设置到图像源
ImageSourceModuleTool imageSourceModuleTool = (ImageSourceModuleTool)VmSolution.Instance["流程1.图像源1"];
imageSourceModuleTool.SetImageData(image);

3 相机采图转模块输入(InputImageData)

public InputImageData CCDToInputImageData(MyCamera.MV_FRAME_OUT frameOut)
{
    InputImageData inputImageData = new InputImageData();
    inputImageData.Names.DataName = "InImage";//只能使用默认名称InImage
    inputImageData.Names.HeightName = "InImageHeight";//默认InImageHeight
    inputImageData.Names.WidthName = "InImageWidth";//默认InImageWidth
    inputImageData.Names.PixelFormatName = "InImagePixelFormat";//默认InImagePixelFormat
    inputImageData.Width = frameOut.stFrameInfo.nWidth;
    inputImageData.Height = frameOut.stFrameInfo.nHeight;
    inputImageData.DataLen = frameOut.stFrameInfo.nFrameLen;

    if (frameOut.stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
    {
        inputImageData.Pixelformat = ImagePixelFormat.IMAGE_PIXEL_FORMAT_MONO8;

    }
    else if (frameOut.stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
    {
        inputImageData.Pixelformat = ImagePixelFormat.IMAGE_PIXEL_FORMAT_RGB24;
    }
    //申请内存
    inputImageData.Data = Marshal.AllocHGlobal((int)frameOut.stFrameInfo.nFrameLen);
    byte[] imagedataBuffer = new byte[(int)frameOut.stFrameInfo.nFrameLen];
    Marshal.Copy(frameOut.pBufAddr, imagedataBuffer, 0, (int)frameOut.stFrameInfo.nFrameLen);
    Marshal.Copy(imagedataBuffer, 0, inputImageData.Data, (int)frameOut.stFrameInfo.nFrameLen);
    return inputImageData;
}
var image= CCDToInputImageData(stFrameOut);
//设置到模块        
var circlefindTool = VmSolution.Instance["流程1.圆查找1"] as IMVSImageEnhanceModuCs.IMVSImageEnhanceModuTool;
circlefindTool.ModuParams.SetInputImage(image);

4 相机采图转算子输入(CmvdImage)

public CMvdImage CCDToCMvdImage(MyCamera.MV_FRAME_OUT frameOut)
{
    VisionDesigner.CMvdImage cMvdImage = new VisionDesigner.CMvdImage();
    VisionDesigner.MVD_IMAGE_DATA_INFO stImageData = new VisionDesigner.MVD_IMAGE_DATA_INFO();
    stImageData.stDataChannel[0].nLen = (uint)(frameOut.stFrameInfo.nFrameLen);
    stImageData.stDataChannel[0].nSize = (uint)(frameOut.stFrameInfo.nFrameLen);
    byte[] m_BufForDriver1 = new byte[frameOut.stFrameInfo.nFrameLen];
    //数据Copy
    Marshal.Copy(frameOut.pBufAddr, m_BufForDriver1, 0, (int)frameOut.stFrameInfo.nFrameLen);
    stImageData.stDataChannel[0].arrDataBytes = m_BufForDriver1;
    if (frameOut.stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
    {
        stImageData.stDataChannel[0].nRowStep = (uint)frameOut.stFrameInfo.nWidth;
        //初始化CMvdImage
        cMvdImage.InitImage((uint)frameOut.stFrameInfo.nWidth, (uint)frameOut.stFrameInfo.nHeight, MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08, stImageData);
    }
    else if (frameOut.stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
    {
        stImageData.stDataChannel[0].nRowStep = (uint)frameOut.stFrameInfo.nWidth * 3;
        //初始化CMvdImage
        cMvdImage.InitImage((uint)frameOut.stFrameInfo.nWidth, (uint)frameOut.stFrameInfo.nHeight, MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3, stImageData);
    }
    return cMvdImage;
}

问题根因
不熟悉相机采图转换为其它类型

3.3 Bitmap转流程输入、Group输入、图像源SDK输入、模块输入、算子输入、算子输出、流程输出图像

描述
环境:VM4.2 + VS2013及以上
现象:Bitmap转换成其他图像类型
解答
Bitmap转换为流程输入图像、Group输入图像、图像源SDK输入图像、模块输入图像、算子输入图像,流程输出图像转换为Bitmap。
1 Bitmap转流程输入(ImageBaseData_V2)、Group输入(ImageBaseData_V2)

public ImageBaseData_V2 BitmapToImageBaseData_V2(Bitmap bmpInputImg)
{
    ImageBaseData_V2 imageBaseData_V2 = new ImageBaseData_V2();
    System.Drawing.Imaging.PixelFormat bitPixelFormat = bmpInputImg.PixelFormat;
    BitmapData bmData = bmpInputImg.LockBits(new Rectangle(0, 0, bmpInputImg.Width, bmpInputImg.Height), ImageLockMode.ReadOnly, bitPixelFormat);//锁定

    if (bitPixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
    {
        Int32 bitmapDataSize = bmData.Stride * bmData.Height;//bitmap图像缓存长度
        int offset = bmData.Stride - bmData.Width;
        Int32 ImageBaseDataSize = bmData.Width * bmData.Height;//imageBaseData_V2图像真正的缓存长度
        byte[] _BitImageBufferBytes = new byte[bitmapDataSize];
        byte[] _ImageBaseDataBufferBytes = new byte[ImageBaseDataSize];
        Marshal.Copy(bmData.Scan0, _BitImageBufferBytes, 0, bitmapDataSize);
        int bitmapIndex = 0;
        int ImageBaseDataIndex = 0;
        for (int i = 0; i < bmData.Height; i++)
        {
            for (int j = 0; j < bmData.Width; j++)
            {
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex++];
            }
            bitmapIndex += offset;//删除冗余数据
        }
        IntPtr _ImageBaseDataIntptr = Marshal.AllocHGlobal(ImageBaseDataSize);
        Marshal.Copy(_ImageBaseDataBufferBytes, 0, _ImageBaseDataIntptr, ImageBaseDataSize);
        imageBaseData_V2 = new ImageBaseData_V2(_ImageBaseDataIntptr, (uint)ImageBaseDataSize, bmData.Width, bmData.Height, VMPixelFormat.VM_PIXEL_MONO_08);
        Marshal.FreeHGlobal(_ImageBaseDataIntptr);
    }
    else if (bitPixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb)
    {
        Int32 bitmapDataSize = bmData.Stride * bmData.Height;//bitmap图像缓存长度
        int offset = bmData.Stride - bmData.Width * 3;
        Int32 ImageBaseDataSize = bmData.Width * bmData.Height * 3;//imageBaseData_V2图像真正的缓存长度
        byte[] _BitImageBufferBytes = new byte[bitmapDataSize];
        byte[] _ImageBaseDataBufferBytes = new byte[ImageBaseDataSize];
        Marshal.Copy(bmData.Scan0, _BitImageBufferBytes, 0, bitmapDataSize);
        int bitmapIndex = 0;
        int ImageBaseDataIndex = 0;
        for (int i = 0; i < bmData.Height; i++)
        {
            for (int j = 0; j < bmData.Width; j++)
            {
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex + 2];//bitmap为BGR,imageBaseData_V2为RGB
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex + 1];
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex];
                bitmapIndex += 3;
            }
            bitmapIndex += offset;
        }
        IntPtr _ImageBaseDataIntptr = Marshal.AllocHGlobal(ImageBaseDataSize);
        Marshal.Copy(_ImageBaseDataBufferBytes, 0, _ImageBaseDataIntptr, ImageBaseDataSize);
        imageBaseData_V2 = new ImageBaseData_V2(_ImageBaseDataIntptr, (uint)ImageBaseDataSize, bmData.Width, bmData.Height, VMPixelFormat.VM_PIXEL_RGB24_C3);
        Marshal.FreeHGlobal(_ImageBaseDataIntptr);
}
bmpInputImg.UnlockBits(bmData);  // 解除锁定
    return imageBaseData_V2;
}

2 Bitmap转图像源SDK输入(ImageBaseData)

public ImageBaseData BitmapToImageBaseData(Bitmap bmpInputImg)
{
    ImageBaseData imageBaseData = new ImageBaseData();
    System.Drawing.Imaging.PixelFormat bitPixelFormat = bmpInputImg.PixelFormat;
    BitmapData bmData = bmpInputImg.LockBits(new Rectangle(0, 0, bmpInputImg.Width, bmpInputImg.Height), ImageLockMode.ReadOnly, bitPixelFormat);//锁定

    if (bitPixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
    {
        Int32 bitmapDataSize = bmData.Stride * bmData.Height;//bitmap图像缓存长度
        int offset = bmData.Stride - bmData.Width;
        Int32 ImageBaseDataSize = bmData.Width * bmData.Height;
        byte[] _BitImageBufferBytes = new byte[bitmapDataSize];
        byte[] _ImageBaseDataBufferBytes = new byte[ImageBaseDataSize];
        Marshal.Copy(bmData.Scan0, _BitImageBufferBytes, 0, bitmapDataSize);
        int bitmapIndex = 0;
        int ImageBaseDataIndex = 0;
        for (int i = 0; i < bmData.Height; i++)
        {
            for (int j = 0; j < bmData.Width; j++)
            {
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex++];
            }
            bitmapIndex += offset;
        }
        imageBaseData = new ImageBaseData(_ImageBaseDataBufferBytes, (uint)ImageBaseDataSize, bmData.Width, bmData.Height, (int)VMPixelFormat.VM_PIXEL_MONO_08);
    }
    else if (bitPixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb)
    {
        Int32 bitmapDataSize = bmData.Stride * bmData.Height;//bitmap图像缓存长度
        int offset = bmData.Stride - bmData.Width * 3;
        Int32 ImageBaseDataSize = bmData.Width * bmData.Height * 3;
        byte[] _BitImageBufferBytes = new byte[bitmapDataSize];
        byte[] _ImageBaseDataBufferBytes = new byte[ImageBaseDataSize];
        Marshal.Copy(bmData.Scan0, _BitImageBufferBytes, 0, bitmapDataSize);
        int bitmapIndex = 0;
        int ImageBaseDataIndex = 0;
        for (int i = 0; i < bmData.Height; i++)
        {
            for (int j = 0; j < bmData.Width; j++)
            {
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex + 2];
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex + 1];
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex];
                bitmapIndex += 3;
            }
            bitmapIndex += offset;
        }
        imageBaseData = new ImageBaseData(_ImageBaseDataBufferBytes, (uint)ImageBaseDataSize, bmData.Width, bmData.Height, (int)VMPixelFormat.VM_PIXEL_RGB24_C3);
}
bmpInputImg.UnlockBits(bmData);  // 解除锁定
    return imageBaseData;
}

3 Bitmap转模块输入(InputImageData)

public InputImageData BitmapToInputImageData(Bitmap bmpInputImg)
{
    InputImageData inputImageData = new InputImageData();
    System.Drawing.Imaging.PixelFormat bitPixelFormat = bmpInputImg.PixelFormat;
    BitmapData bmData = bmpInputImg.LockBits(new Rectangle(0, 0, bmpInputImg.Width, bmpInputImg.Height), ImageLockMode.ReadOnly, bitPixelFormat);//锁定

    inputImageData.Names.DataName = "InImage";//只能使用默认名称InImage
    inputImageData.Names.HeightName = "InImageHeight";//默认InImageHeight
    inputImageData.Names.WidthName = "InImageWidth";//默认InImageWidth
    inputImageData.Names.PixelFormatName = "InImagePixelFormat";//默认InImagePixelFormat
    inputImageData.Width = bmData.Width;
    inputImageData.Height = bmData.Height;

    if (bitPixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
    {
        Int32 bitmapDataSize = bmData.Stride * bmData.Height;//bitmap图像缓存长度
        int offset = bmData.Stride - bmData.Width;
        Int32 ImageBaseDataSize = bmData.Width * bmData.Height;
        byte[] _BitImageBufferBytes = new byte[bitmapDataSize];
        byte[] _ImageBaseDataBufferBytes = new byte[ImageBaseDataSize];
        Marshal.Copy(bmData.Scan0, _BitImageBufferBytes, 0, bitmapDataSize);
        int bitmapIndex = 0;
        int ImageBaseDataIndex = 0;
        for (int i = 0; i < bmData.Height; i++)
        {
            for (int j = 0; j < bmData.Width; j++)
            {
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex++];
            }
            bitmapIndex += offset;
        }
        inputImageData.Pixelformat = ImagePixelFormat.IMAGE_PIXEL_FORMAT_MONO8;
        inputImageData.DataLen = (uint)ImageBaseDataSize;
        inputImageData.Data = Marshal.AllocHGlobal(ImageBaseDataSize);//inputImageData.Data需要申请内存;
        Marshal.Copy(_ImageBaseDataBufferBytes, 0, inputImageData.Data, _ImageBaseDataBufferBytes.Length);
    }
    else if (bitPixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb)
    {
        Int32 bitmapDataSize = bmData.Stride * bmData.Height;//bitmap图像缓存长度
        int offset = bmData.Stride - bmData.Width * 3;
        Int32 ImageBaseDataSize = bmData.Width * bmData.Height * 3;
        byte[] _BitImageBufferBytes = new byte[bitmapDataSize];
        byte[] _ImageBaseDataBufferBytes = new byte[ImageBaseDataSize];
        Marshal.Copy(bmData.Scan0, _BitImageBufferBytes, 0, bitmapDataSize);
        int bitmapIndex = 0;
        int ImageBaseDataIndex = 0;
        for (int i = 0; i < bmData.Height; i++)
        {
            for (int j = 0; j < bmData.Width; j++)
            {
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex + 2];
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex + 1];
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex];
                bitmapIndex += 3;
            }
            bitmapIndex += offset;
        }
        inputImageData.Pixelformat = ImagePixelFormat.IMAGE_PIXEL_FORMAT_RGB24;
        inputImageData.DataLen = (uint)ImageBaseDataSize;
        inputImageData.Data = Marshal.AllocHGlobal(ImageBaseDataSize);//inputImageData.Data需要申请内存;
        Marshal.Copy(_ImageBaseDataBufferBytes, 0, inputImageData.Data, _ImageBaseDataBufferBytes.Length);
    }
    bmpInputImg.UnlockBits(bmData);  // 解除锁定
    return inputImageData;
}

4 Bitmap与算子(CmvdImage)互转

public CMvdImage BitmapToCMvdImage(Bitmap bmpInputImg)
{
    CMvdImage cMvdImage = new CMvdImage();
    System.Drawing.Imaging.PixelFormat bitPixelFormat = bmpInputImg.PixelFormat;
    BitmapData bmData = bmpInputImg.LockBits(new Rectangle(0, 0, bmpInputImg.Width, bmpInputImg.Height), ImageLockMode.ReadOnly, bitPixelFormat);//锁定

    if (bitPixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
    {
        Int32 bitmapDataSize = bmData.Stride * bmData.Height;//bitmap图像缓存长度
        int offset = bmData.Stride - bmData.Width;
        Int32 ImageBaseDataSize = bmData.Width * bmData.Height;
        byte[] _BitImageBufferBytes = new byte[bitmapDataSize];
        byte[] _ImageBaseDataBufferBytes = new byte[ImageBaseDataSize];
        Marshal.Copy(bmData.Scan0, _BitImageBufferBytes, 0, bitmapDataSize);
        int bitmapIndex = 0;
        int ImageBaseDataIndex = 0;
        for (int i = 0; i < bmData.Height; i++)
        {
            for (int j = 0; j < bmData.Width; j++)
            {
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex++];
            }
            bitmapIndex += offset;
        }
        MVD_IMAGE_DATA_INFO stImageData = new MVD_IMAGE_DATA_INFO();
        stImageData.stDataChannel[0].nRowStep = (uint)bmData.Width;
        stImageData.stDataChannel[0].nLen = (uint)ImageBaseDataSize;
        stImageData.stDataChannel[0].nSize = (uint)ImageBaseDataSize;
        stImageData.stDataChannel[0].arrDataBytes = _ImageBaseDataBufferBytes;
        cMvdImage.InitImage((uint)bmData.Width, (uint)bmData.Height, MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08, stImageData);
    }
    else if (bitPixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb)
    {
        Int32 bitmapDataSize = bmData.Stride * bmData.Height;//bitmap图像缓存长度
        int offset = bmData.Stride - bmData.Width * 3;
        Int32 ImageBaseDataSize = bmData.Width * bmData.Height * 3;
        byte[] _BitImageBufferBytes = new byte[bitmapDataSize];
        byte[] _ImageBaseDataBufferBytes = new byte[ImageBaseDataSize];
        Marshal.Copy(bmData.Scan0, _BitImageBufferBytes, 0, bitmapDataSize);
        int bitmapIndex = 0;
        int ImageBaseDataIndex = 0;
        for (int i = 0; i < bmData.Height; i++)
        {
            for (int j = 0; j < bmData.Width; j++)
            {
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex + 2];
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex + 1];
                _ImageBaseDataBufferBytes[ImageBaseDataIndex++] = _BitImageBufferBytes[bitmapIndex];
                bitmapIndex += 3;
            }
            bitmapIndex += offset;
        }
        MVD_IMAGE_DATA_INFO stImageData = new MVD_IMAGE_DATA_INFO();
        stImageData.stDataChannel[0].nRowStep = (uint)bmData.Width * 3;
        stImageData.stDataChannel[0].nLen = (uint)ImageBaseDataSize;
        stImageData.stDataChannel[0].nSize = (uint)ImageBaseDataSize;
        stImageData.stDataChannel[0].arrDataBytes = _ImageBaseDataBufferBytes;
        cMvdImage.InitImage((uint)bmData.Width, (uint)bmData.Height, MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3, stImageData);
    }
    bmpInputImg.UnlockBits(bmData);  // 解除锁定
    return cMvdImage;
}
public Bitmap CMvdImageToBitmap(CMvdImage cMvdImage)
{
    Bitmap bmpInputImg= null;
    byte[] buffer = new byte[cMvdImage.GetImageData(0).arrDataBytes.Length];
    buffer = cMvdImage.GetImageData(0).arrDataBytes;

    if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 == cMvdImage.PixelFormat)
    {
        Int32 imageWidth = Convert.ToInt32(cMvdImage.Width);
        Int32 imageHeight = Convert.ToInt32(cMvdImage.Height);
        System.Drawing.Imaging.PixelFormat bitMaPixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
        bmpInputImg = new Bitmap(imageWidth, imageHeight, bitMaPixelFormat);
        int offset = imageWidth % 4 != 0 ? (4 - imageWidth % 4) : 0;//添加冗余位,变成4的倍数
        int strid = imageWidth + offset;
        int bitmapBytesLenth = strid * imageHeight;
        byte[] bitmapDataBytes = new byte[bitmapBytesLenth];
        for (int i = 0; i < imageHeight; i++)
        {
            for (int j = 0; j < strid; j++)
            {
                int bitIndex = i * strid + j;
                int mvdIndex = i * imageWidth + j;
                if (j >= imageWidth)
                {
                    bitmapDataBytes[bitIndex] = 0;//冗余位填充0
                }
                else
                {
                    bitmapDataBytes[bitIndex] = buffer[mvdIndex];
                }
            }
        }
        BitmapData bitmapData = bmpInputImg.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.WriteOnly, bitMaPixelFormat);
        IntPtr imageBufferPtr = bitmapData.Scan0;
        Marshal.Copy(bitmapDataBytes, 0, imageBufferPtr, bitmapBytesLenth);
        bmpInputImg.UnlockBits(bitmapData);

        var colorPalettes = bmpInputImg.Palette;
        for (int j = 0; j < 256; j++)
        {
            colorPalettes.Entries[j] = Color.FromArgb(j, j, j);
        }
        bmpInputImg.Palette = colorPalettes;
    }
    else if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImage.PixelFormat)
    {
        Int32 imageWidth = Convert.ToInt32(cMvdImage.Width);
        Int32 imageHeight = Convert.ToInt32(cMvdImage.Height);
        System.Drawing.Imaging.PixelFormat bitMaPixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
        bmpInputImg = new Bitmap(imageWidth, imageHeight, bitMaPixelFormat);
        int offset = imageWidth % 4 != 0 ? (4 - (imageWidth * 3) % 4) : 0;//添加冗余位,变成4的倍数
        int strid = imageWidth * 3 + offset;
        int bitmapBytesLenth = strid * imageHeight;
        byte[] bitmapDataBytes = new byte[bitmapBytesLenth];
        for (int i = 0; i < imageHeight; i++)
        {
            for (int j = 0; j < imageWidth; j++)
            {
                int mvdIndex = i * imageWidth * 3 + j * 3;
                int bitIndex = i * strid + j * 3;
                bitmapDataBytes[bitIndex] = buffer[mvdIndex + 2];
                bitmapDataBytes[bitIndex + 1] = buffer[mvdIndex + 1];
                bitmapDataBytes[bitIndex + 2] = buffer[mvdIndex];
            }
            for (int k = 0; k < offset; k++)
            {
                bitmapDataBytes[i * strid + imageWidth * 3 + k] = 0;
            }
        }
        BitmapData bitmapData = bmpInputImg.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.WriteOnly, bitMaPixelFormat);
        IntPtr imageBufferPtr = bitmapData.Scan0;
        Marshal.Copy(bitmapDataBytes, 0, imageBufferPtr, bitmapBytesLenth);
        bmpInputImg.UnlockBits(bitmapData);
    }  
    return bmpInputImg;
}

5 流程输出(ImageBaseData_V2)转Bitmap

public Bitmap ImageBaseData_V2ToBitmap(ImageBaseData_V2 imageBaseData_V2)
{
    Bitmap bmpInputImg = null;
    byte[] buffer = new byte[imageBaseData_V2.DataLen];
    Marshal.Copy(imageBaseData_V2.ImageData, buffer, 0, buffer.Length);

    if (VMPixelFormat.VM_PIXEL_MONO_08 == imageBaseData_V2.Pixelformat)
    {
        Int32 imageWidth = Convert.ToInt32(imageBaseData_V2.Width);
        Int32 imageHeight = Convert.ToInt32(imageBaseData_V2.Height);
        System.Drawing.Imaging.PixelFormat bitMaPixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
        bmpInputImg = new Bitmap(imageWidth, imageHeight, bitMaPixelFormat);
        int offset = imageWidth % 4 != 0 ? (4 - imageWidth % 4) : 0;//添加冗余位,变成4的倍数
        int strid = imageWidth + offset;
        int bitmapBytesLenth = strid * imageHeight;
        byte[] bitmapDataBytes = new byte[bitmapBytesLenth];
        for (int i = 0; i < imageHeight; i++)
        {
            for (int j = 0; j < strid; j++)
            {
                int bitIndex = i * strid + j;
                int mvdIndex = i * imageWidth + j;
                if (j >= imageWidth)
                {
                    bitmapDataBytes[bitIndex] = 0;//冗余位填充0
                }
                else
                {
                    bitmapDataBytes[bitIndex] = buffer[mvdIndex];
                }
            }
        }
        BitmapData bitmapData = bmpInputImg.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.WriteOnly, bitMaPixelFormat);
        IntPtr imageBufferPtr = bitmapData.Scan0;
        Marshal.Copy(bitmapDataBytes, 0, imageBufferPtr, bitmapBytesLenth);
        bmpInputImg.UnlockBits(bitmapData);

        var colorPalettes = bmpInputImg.Palette;
        for (int j = 0; j < 256; j++)
        {
            colorPalettes.Entries[j] = Color.FromArgb(j, j, j);
        }
        bmpInputImg.Palette = colorPalettes;
    }
    else if (VMPixelFormat.VM_PIXEL_RGB24_C3 == imageBaseData_V2.Pixelformat)
    {
        Int32 imageWidth = Convert.ToInt32(imageBaseData_V2.Width);
        Int32 imageHeight = Convert.ToInt32(imageBaseData_V2.Height);
        System.Drawing.Imaging.PixelFormat bitMaPixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
        bmpInputImg = new Bitmap(imageWidth, imageHeight, bitMaPixelFormat);
        int offset = imageWidth % 4 != 0 ? (4 - (imageWidth * 3) % 4) : 0;//添加冗余位,变成4的倍数
        int strid = imageWidth * 3 + offset;
        int bitmapBytesLenth = strid * imageHeight;
        byte[] bitmapDataBytes = new byte[bitmapBytesLenth];
        for (int i = 0; i < imageHeight; i++)
        {
            for (int j = 0; j < imageWidth; j++)
            {
                int mvdIndex = i * imageWidth * 3 + j * 3;
                int bitIndex = i * strid + j * 3;
                bitmapDataBytes[bitIndex] = buffer[mvdIndex + 2];
                bitmapDataBytes[bitIndex + 1] = buffer[mvdIndex + 1];
                bitmapDataBytes[bitIndex + 2] = buffer[mvdIndex];
            }
            for (int k = 0; k < offset; k++)
            {
                bitmapDataBytes[i * strid + imageWidth * 3 + k] = 0;
            }
        }
        BitmapData bitmapData = bmpInputImg.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.WriteOnly, bitMaPixelFormat);
        IntPtr imageBufferPtr = bitmapData.Scan0;
        Marshal.Copy(bitmapDataBytes, 0, imageBufferPtr, bitmapBytesLenth);
        bmpInputImg.UnlockBits(bitmapData);
    }
    return bmpInputImg;
}

问题根因
不熟悉Bitmap转换为其它类型

3.4 Mat转流程输入、Group输入、图像源SDK输入、模块输入、算子输入、算子输出、流程输出、脚本图像

描述
环境:VM4.2 + VS2013及以上
现象:Mat转换成其他图像类型
解答
Mat转换为流程输入图像、Group输入图像、图像源SDK输入图像、模块输入图像、算子输入图像,算子输出图像转Mat,流程输出图像转换为Mat,Mat与脚本图像互转。
1 Mat转流程输入(ImageBaseData_V2)、Group输入(ImageBaseData_V2)

public ImageBaseData_V2 MatToImageBaseData_V2(Mat matInputImg)
{
    ImageBaseData_V2 imageBaseData_V2 = new ImageBaseData_V2();
    uint dataLen = (uint)(matInputImg.Width * matInputImg.Height * matInputImg.Channels());
    if (1 == matInputImg.Channels())
    {
        imageBaseData_V2 = new ImageBaseData_V2(matInputImg.Ptr(0), dataLen, matInputImg.Width, matInputImg.Height, VMPixelFormat.VM_PIXEL_MONO_08);
    }
    else if (3 == matInputImg.Channels())
    {
        //交换R与B通道
        Cv2.CvtColor(matInputImg, matInputImg, ColorConversionCodes.BGR2RGB);
        imageBaseData_V2 = new ImageBaseData_V2(matInputImg.Ptr(0), dataLen, matInputImg.Width, matInputImg.Height, VMPixelFormat.VM_PIXEL_RGB24_C3);
    }
    return imageBaseData_V2;
}

2 Mat转图像源SDK输入(ImageBaseData)

public ImageBaseData MatToImageBaseData(Mat matInputImg)
{
    ImageBaseData imageBaseData = new ImageBaseData();
    uint dataLen = (uint)(matInputImg.Width * matInputImg.Height * matInputImg.Channels());
    byte[] buffer = new byte[dataLen];
    Marshal.Copy(matInputImg.Ptr(0), buffer, 0, buffer.Length);
    if (1 == matInputImg.Channels())
    {
        imageBaseData = new ImageBaseData(buffer, dataLen, matInputImg.Width, matInputImg.Height, (int)VMPixelFormat.VM_PIXEL_MONO_08);
    }
    else if (3 == matInputImg.Channels())
    {
        //交换R与B通道
        for (int i = 0; i < buffer.Length - 2; i += 3)
        {
            byte temp = buffer[i];
            buffer[i] = buffer[i + 2];
            buffer[i + 2] = temp;
        }
        imageBaseData = new ImageBaseData(buffer, dataLen, matInputImg.Width, matInputImg.Height, (int)VMPixelFormat.VM_PIXEL_RGB24_C3);
    }
    return imageBaseData;
}

3 Mat转模块输入(InputImageData)

public InputImageData MatToInputImageData(Mat matInputImg)
{
    InputImageData inputImageData = new InputImageData();
    uint dataLen = (uint)(matInputImg.Width * matInputImg.Height * matInputImg.Channels());
    byte[] buffer = new byte[dataLen];
    Marshal.Copy(matInputImg.Ptr(0), buffer, 0, buffer.Length);

    inputImageData.Names.DataName = "InImage";//只能使用默认名称InImage
    inputImageData.Names.HeightName = "InImageHeight";//默认InImageHeight
    inputImageData.Names.WidthName = "InImageWidth";//默认InImageWidth
    inputImageData.Names.PixelFormatName = "InImagePixelFormat";//默认InImagePixelFormat
    inputImageData.Width = matInputImg.Width;
    inputImageData.Height = matInputImg.Height;
    inputImageData.DataLen = dataLen;
    //inputImageData.Data需要申请内存
    inputImageData.Data = Marshal.AllocHGlobal((int)dataLen);

    if (1 == matInputImg.Channels())
    {
        inputImageData.Pixelformat = ImagePixelFormat.IMAGE_PIXEL_FORMAT_MONO8;
        Marshal.Copy(buffer, 0, inputImageData.Data, buffer.Length);
    }
    else if (3 == matInputImg.Channels())
    {
        //交换R与B通道
        for (int i = 0; i < buffer.Length - 2; i += 3)
        {
            byte temp = buffer[i];
            buffer[i] = buffer[i + 2];
            buffer[i + 2] = temp;
        }
        inputImageData.Pixelformat = ImagePixelFormat.IMAGE_PIXEL_FORMAT_RGB24;
        Marshal.Copy(buffer, 0, inputImageData.Data, buffer.Length);
    }
    return inputImageData;
}

4 Mat与算子图像(CmvdImage)互转

public CMvdImage MatToCMvdImage(Mat matInputImg)
{
    CMvdImage cMvdImage = new CMvdImage();
    uint dataLen = (uint)(matInputImg.Width * matInputImg.Height * matInputImg.Channels());
    byte[] buffer = new byte[dataLen];
    Marshal.Copy(matInputImg.Ptr(0), buffer, 0, buffer.Length);
    if (1 == matInputImg.Channels())
    {
        MVD_IMAGE_DATA_INFO stImageData = new MVD_IMAGE_DATA_INFO();
        stImageData.stDataChannel[0].nRowStep = (uint)matInputImg.Width;
        stImageData.stDataChannel[0].nLen = dataLen;
        stImageData.stDataChannel[0].nSize = dataLen;
        stImageData.stDataChannel[0].arrDataBytes = buffer;
        cMvdImage.InitImage((uint)matInputImg.Width, (uint)matInputImg.Height, MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08, stImageData);
    }
    else if (3 == matInputImg.Channels())
    {
        //交换R与B通道
        for (int i = 0; i < buffer.Length - 2; i += 3)
        {
            byte temp = buffer[i];
            buffer[i] = buffer[i + 2];
            buffer[i + 2] = temp;
        }

        MVD_IMAGE_DATA_INFO stImageData = new MVD_IMAGE_DATA_INFO();
        stImageData.stDataChannel[0].nRowStep = (uint)matInputImg.Width * 3;
        stImageData.stDataChannel[0].nLen = dataLen;
        stImageData.stDataChannel[0].nSize = dataLen;
        stImageData.stDataChannel[0].arrDataBytes = buffer;
        cMvdImage.InitImage((uint)matInputImg.Width, (uint)matInputImg.Height, MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3, stImageData);
    }
    return cMvdImage;
}


public Mat CMvdImageToMat(CMvdImage cMvdImage)
{
    Mat matInputImg = new Mat();
    cMvdImage.InitImage("D:\\2.jpg");
    byte[] buffer = new byte[cMvdImage.GetImageData(0).arrDataBytes.Length];
    buffer = cMvdImage.GetImageData(0).arrDataBytes;

    if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 == cMvdImage.PixelFormat)
    {
        matInputImg.Create((int)cMvdImage.Height, (int)cMvdImage.Width, MatType.CV_8UC1);
        Marshal.Copy(buffer, 0, matInputImg.Ptr(0), buffer.Length);
    }
    else if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImage.PixelFormat)
    {
        matInputImg.Create((int)cMvdImage.Height, (int)cMvdImage.Width, MatType.CV_8UC3);

        //交换R与B通道
        for (int i = 0; i < buffer.Length - 2; i += 3)
        {
            byte temp = buffer[i];
            buffer[i] = buffer[i + 2];
            buffer[i + 2] = temp;
        }
        Marshal.Copy(buffer, 0, matInputImg.Ptr(0), buffer.Length);
    }
    return matInputImg;
}

5 流程输出(ImageBaseData_V2)转Mat

public Mat ImageBaseData_V2ToMat(ImageBaseData_V2 imageBaseData_V2)
{
    Mat matInputImg = new Mat();
    byte[] buffer = new byte[imageBaseData_V2.DataLen];
    Marshal.Copy(imageBaseData_V2.ImageData, buffer, 0, buffer.Length);

    if (VMPixelFormat.VM_PIXEL_MONO_08 == imageBaseData_V2.Pixelformat)
    {
        matInputImg.Create(imageBaseData_V2.Height, imageBaseData_V2.Width, MatType.CV_8UC1);
        Marshal.Copy(buffer, 0, matInputImg.Ptr(0), buffer.Length);
    }
    else if (VMPixelFormat.VM_PIXEL_RGB24_C3 == imageBaseData_V2.Pixelformat)
    {
        matInputImg.Create(imageBaseData_V2.Height, imageBaseData_V2.Width, MatType.CV_8UC3);

        //交换R与B通道
        for (int i = 0; i < buffer.Length - 2; i += 3)
        {
            byte temp = buffer[i];
            buffer[i] = buffer[i + 2];
            buffer[i + 2] = temp;
        }
        Marshal.Copy(buffer, 0, matInputImg.Ptr(0), buffer.Length);
    }
    return matInputImg;
}

6 Mat与脚本图像(ImageData)互转

public ImageData MatToImageData(Mat matImage)
{
    ImageData imgOut = new ImageData();
    byte[] buffer = new Byte[matImage.Width * matImage.Height * matImage.Channels()];
    Marshal.Copy(matImage.Ptr(0), buffer, 0, buffer.Length);
    if (1 == matImage.Channels())
    {
        imgOut.Buffer = buffer;
        imgOut.Width = matImage.Width;
        imgOut.Heigth = matImage.Height;
        imgOut.PixelFormat = ImagePixelFormate.MONO8;
    }
    else if (3 == matImage.Channels())
    {
        //交换R与B通道
        for (int i = 0; i < buffer.Length - 2; i += 3)
        {
            byte temp = buffer[i];
            buffer[i] = buffer[i + 2];
            buffer[i + 2] = temp;
        }

        imgOut.Buffer = buffer;
        imgOut.Width = matImage.Width;
        imgOut.Heigth = matImage.Height;
        imgOut.PixelFormat = ImagePixelFormate.RGB24;
    }
    return imgOut;
}
public Mat ImageDataToMat(ImageData img)
{
    Mat matImage = new Mat();
    if(ImagePixelFormate.MONO8 == img.PixelFormat)
    {
        matImage = Mat.Zeros(img.Heigth, img.Width, MatType.CV_8UC1);
        IntPtr grayPtr = Marshal.AllocHGlobal(img.Width * img.Heigth);
        Marshal.Copy(img.Buffer, 0, matImage.Ptr(0), img.Buffer.Length);

        //用完记得释放指针 
        Marshal.FreeHGlobal(grayPtr);
    }
    else if (ImagePixelFormate.RGB24 == img.PixelFormat)
    {
        matImage = Mat.Zeros(img.Heigth, img.Width, MatType.CV_8UC3);
        IntPtr rgbPtr = Marshal.AllocHGlobal(img.Width * img.Heigth * 3);
        Marshal.Copy(img.Buffer, 0, matImage.Ptr(0), img.Buffer.Length);
        Cv2.CvtColor(matImage, matImage, ColorConversionCodes.RGB2BGR);

        //用完记得释放指针 
        Marshal.FreeHGlobal(rgbPtr);
    }
    return matImage;
}

问题根因
不熟悉Mat转换为其它类型

3.5 Halcon转流程输入、Group输入、图像源SDK输入、模块输入、算子输入、算子输出、流程输出、脚本图像

描述
环境:VM4.2 + VS2013及以上
现象:Halcon转换成其他图像类型
解答
Halcon图像转换为流程输入图像、Group输入图像、图像源SDK输入图像、模块输入图像、算子输入图像,算子输出图像转Halcon图像,流程输出图像转换为Halcon图像,Halcon图像与脚本图像互转。
1 Halcon图像转流程输入(ImageBaseData_V2)、Group输入(ImageBaseData_V2)

public static ImageBaseData_V2 HalconImageToImageBaseDataV2(HObject hImageObj)
{
    try
    {
        ImageBaseData_V2 imageBaseData = new ImageBaseData_V2();
        HTuple imageWidth = 0;
        HTuple imageHeight = 0;
        HTuple objClass = hImageObj.GetObjClass();
        if (objClass.S.Equals("image"))
        {
            HTuple imageType;
            HOperatorSet.GetImageType(hImageObj, out imageType);
            if (imageType.S.Equals("byte"))
            {
                //获取图像通道数
                HTuple channels = 0;
                HOperatorSet.CountChannels(hImageObj, out channels);
                //如果是单通道
                if (channels.I == 1)
                {
                    HTuple imagePointer;
                    HOperatorSet.GetImagePointer1(hImageObj, out imagePointer, out imageType, out imageWidth, out imageHeight);
                    imageBaseData.Width = imageWidth.I;
                    imageBaseData.Height = imageHeight.I;
                    imageBaseData.Pixelformat = VMPixelFormat.VM_PIXEL_MONO_08;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    imageBaseData.DataLen = (uint)(stride * imageBaseData.Height);
                    imageBaseData.ImageData = imagePointer;
                }
                //如果是三通道
                else if (channels.I == 3)
                {
                    HTuple redChannel;
                    HTuple greenChannel;
                    HTuple blueChannel;
                    HOperatorSet.GetImagePointer3(hImageObj, out redChannel, out greenChannel, out blueChannel, out imageType, out imageWidth, out imageHeight);
                    imageBaseData.Width = imageWidth.I;
                    imageBaseData.Height = imageHeight.I;
                    imageBaseData.Pixelformat = VMPixelFormat.VM_PIXEL_RGB24_C3;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    byte[] imageRedBuffer = new byte[stride * imageHeight.I];
                    byte[] imageGreenBuffer = new byte[stride * imageHeight.I];
                    byte[] imageBlueBuffer = new byte[stride * imageHeight.I];
                    Marshal.Copy(redChannel, imageRedBuffer, 0, imageRedBuffer.Length);
                    Marshal.Copy(greenChannel, imageGreenBuffer, 0, imageGreenBuffer.Length);
                    Marshal.Copy(blueChannel, imageBlueBuffer, 0, imageBlueBuffer.Length);
                    byte[] imageBuffer = new byte[stride * imageHeight.I * 3];
                    for (int row = 0; row < imageHeight.I; row++)
                    {
                        for (int col = 0, index = 0; col < imageWidth.I; col++, index += 3)
                        {
                            imageBuffer[index] = imageRedBuffer[row * imageWidth + col];
                            imageBuffer[index + 1] = imageGreenBuffer[row * imageWidth + col];
                            imageBuffer[index + 2] = imageBlueBuffer[row * imageWidth + col];
                        }
                    }
                    imageBaseData.DataLen = (uint)(stride * imageBaseData.Height * 3);
                    imageBaseData.ImageData = Marshal.UnsafeAddrOfPinnedArrayElement(imageBuffer, 0);
                }
                else
                {
                    hImageObj?.Dispose();
                    throw new Exception("不支持单通道,三通道以外的图像");
                }
            }
            else
            {
                hImageObj?.Dispose();
                throw new Exception("不支持8bit以外的位深度图像");
            }
        }
        else
        {
            hImageObj?.Dispose();
            throw new Exception("HObject非图像类型对象");
        }
        return imageBaseData;
    }
    catch (Exception ex)
    {
        hImageObj?.Dispose();
        throw new Exception(ex.Message);
    }
}

2 Halcon图像转图像源SDK输入(ImageBaseData)

public static ImageBaseData HalconImageToImageBaseData(HObject hImageObj)
{
    try
    {
        ImageBaseData imageBaseData = new ImageBaseData();
        HTuple imageWidth = 0;
        HTuple imageHeight = 0;
        HTuple objClass = hImageObj.GetObjClass();
        if (objClass.S.Equals("image"))
        {
            HTuple imageType;
            HOperatorSet.GetImageType(hImageObj, out imageType);
            if (imageType.S.Equals("byte"))
            {
                //获取图像通道数
                HTuple channels = 0;
                HOperatorSet.CountChannels(hImageObj, out channels);
                //如果是单通道
                if (channels.I == 1)
                {
                    HTuple imagePointer;
                    HOperatorSet.GetImagePointer1(hImageObj, out imagePointer, out imageType, out imageWidth, out imageHeight);
                    imageBaseData.Width = imageWidth.I;
                    imageBaseData.Height = imageHeight.I;
                    imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_MONO_08;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    imageBaseData.DataLen = (uint)(stride * imageBaseData.Height);
                    imageBaseData.ImageData = new byte[stride * imageHeight.I];
                    Marshal.Copy(imagePointer, imageBaseData.ImageData, 0, stride * imageHeight.I);
                }
                //如果是三通道
                else if (channels.I == 3)
                {
                    HTuple redChannel;
                    HTuple greenChannel;
                    HTuple blueChannel;
                    HOperatorSet.GetImagePointer3(hImageObj, out redChannel, out greenChannel, out blueChannel, out imageType, out imageWidth, out imageHeight);
                    imageBaseData.Width = imageWidth.I;
                    imageBaseData.Height = imageHeight.I;
                    imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_RGB24_C3;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    imageBaseData.DataLen = (uint)(stride * imageBaseData.Height * 3);
                    imageBaseData.ImageData = new byte[stride * imageHeight.I * 3];
                    byte[] imageRedBuffer = new byte[stride * imageHeight.I];
                    byte[] imageGreenBuffer = new byte[stride * imageHeight.I];
                    byte[] imageBlueBuffer = new byte[stride * imageHeight.I];
                    Marshal.Copy(redChannel.IP, imageRedBuffer, 0, imageRedBuffer.Length);
                    Marshal.Copy(greenChannel.IP, imageGreenBuffer, 0, imageGreenBuffer.Length);
                    Marshal.Copy(blueChannel.IP, imageBlueBuffer, 0, imageBlueBuffer.Length);
                    for (int row = 0; row < imageHeight.I; row++)
                    {
                        for (int col = 0, index = 0; col < imageWidth.I; col++, index += 3)
                        {
                            imageBaseData.ImageData[index] = imageRedBuffer[row * imageWidth + col];
                            imageBaseData.ImageData[index + 1] = imageGreenBuffer[row * imageWidth + col];
                            imageBaseData.ImageData[index + 2] = imageBlueBuffer[row * imageWidth + col];
                        }
                    }
                }
                else
                {
                    hImageObj?.Dispose();
                    throw new Exception("不支持单通道,三通道以外的图像");
                }
            }
            else
            {
                hImageObj?.Dispose();
                throw new Exception("不支持8bit以外的位深度图像");
            }
        }
        else
        {
            hImageObj?.Dispose();
            throw new Exception("HObject非图像类型对象");
        }
        return imageBaseData;
    }
    catch (Exception ex)
    {
        hImageObj?.Dispose();
        throw new Exception(ex.Message);
    }
}

3 Halcon图像转模块输入(InputImageData)

public static InputImageData HalconImageToModuleInputImage(HObject hImageObj)
{
    try
    {
        InputImageData inputImageData = new InputImageData();
        HTuple imageWidth = 0;
        HTuple imageHeight = 0;
        HTuple objClass = hImageObj.GetObjClass();
        if (objClass.S.Equals("image"))
        {
            HTuple imageType;
            HOperatorSet.GetImageType(hImageObj, out imageType);
            if (imageType.S.Equals("byte"))
            {
                //获取图像通道数
                HTuple channels = 0;
                HOperatorSet.CountChannels(hImageObj, out channels);
                //如果是单通道
                if (channels.I == 1)
                {
                    HTuple imagePointer;
                    HOperatorSet.GetImagePointer1(hImageObj, out imagePointer, out imageType, out imageWidth, out imageHeight);
                    inputImageData.Width = imageWidth.I;
                    inputImageData.Height = imageHeight.I;
                    inputImageData.Pixelformat = ImagePixelFormat.IMAGE_PIXEL_FORMAT_MONO8;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    inputImageData.DataLen = (uint)(stride * inputImageData.Height);
                    inputImageData.Data = imagePointer;
                    inputImageData.Names.DataName = "InImage";
                    inputImageData.Names.WidthName = "InImageWidth";
                    inputImageData.Names.HeightName = "InImageHeight";
                    inputImageData.Names.PixelFormatName = "InImagePixelFormat";
                }
                //如果是三通道
                else if (channels.I == 3)
                {
                    HTuple redChannel;
                    HTuple greenChannel;
                    HTuple blueChannel;
                    HOperatorSet.GetImagePointer3(hImageObj, out redChannel, out greenChannel, out blueChannel, out imageType, out imageWidth, out imageHeight);
                    inputImageData.Width = imageWidth.I;
                    inputImageData.Height = imageHeight.I;
                    inputImageData.Pixelformat = ImagePixelFormat.IMAGE_PIXEL_FORMAT_RGB24;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    byte[] imageRedBuffer = new byte[stride * imageHeight.I];
                    byte[] imageGreenBuffer = new byte[stride * imageHeight.I];
                    byte[] imageBlueBuffer = new byte[stride * imageHeight.I];
                    Marshal.Copy(redChannel.IP, imageRedBuffer, 0, imageRedBuffer.Length);
                    Marshal.Copy(greenChannel.IP, imageGreenBuffer, 0, imageGreenBuffer.Length);
                    Marshal.Copy(blueChannel.IP, imageBlueBuffer, 0, imageBlueBuffer.Length);
                    byte[] imageBuffer = new byte[stride * imageHeight * 3];
                    for (int row = 0; row < imageHeight.I; row++)
                    {
                        for (int col = 0, index = 0; col < imageWidth.I; col++, index += 3)
                        {
                            imageBuffer[index] = imageRedBuffer[row * imageWidth + col];
                            imageBuffer[index + 1] = imageGreenBuffer[row * imageWidth + col];
                            imageBuffer[index + 2] = imageBlueBuffer[row * imageWidth + col];
                        }
                    }
                    inputImageData.DataLen = (uint)(stride * inputImageData.Height * 3);
                    inputImageData.Data = Marshal.UnsafeAddrOfPinnedArrayElement(imageBuffer, 0);
                    inputImageData.Names.DataName = "InImage";
                    inputImageData.Names.WidthName = "InImageWidth";
                    inputImageData.Names.HeightName = "InImageHeight";
                    inputImageData.Names.PixelFormatName = "InImagePixelFormat";
                }
                else
                {
                    hImageObj?.Dispose();
                    throw new Exception("不支持单通道,三通道以外的图像");
                }
            }
            else
            {
                hImageObj?.Dispose();
                throw new Exception("不支持8bit以外的位深度图像");
            }
        }
        else
        {
            hImageObj?.Dispose();
            throw new Exception("HObject非图像类型对象");
        }
        return inputImageData;
    }
    catch (Exception ex)
    {
        hImageObj?.Dispose();
        throw new Exception(ex.Message);
    }
}

4 Halcon图像与算子图像(CmvdImage)互转

public static CMvdImage HalconImageToCMvdImage(HObject hImageObj)
{
    try
    {
        CMvdImage image = new CMvdImage();
        HTuple imageWidth = 0;
        HTuple imageHeight = 0;
        HTuple objClass = hImageObj.GetObjClass();
        if (objClass.S.Equals("image"))
        {
            HTuple imageType;
            HOperatorSet.GetImageType(hImageObj, out imageType);
            if (imageType.S.Equals("byte"))
            {
                //获取图像通道数
                HTuple channels = 0;
                HOperatorSet.CountChannels(hImageObj, out channels);
                //如果是单通道
                if (channels.I == 1)
                {
                    HTuple imagePointer;
                    HOperatorSet.GetImagePointer1(hImageObj, out imagePointer, out imageType, out imageWidth, out imageHeight);
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    MVD_IMAGE_DATA_INFO imageDataInfo = new MVD_IMAGE_DATA_INFO();
                    imageDataInfo.stDataChannel = new MVD_DATA_CHANNEL_INFO[4];
                    imageDataInfo.stDataChannel[0] = new MVD_DATA_CHANNEL_INFO();
                    imageDataInfo.stDataChannel[0].arrDataBytes = new byte[stride * imageHeight.I];
                    imageDataInfo.stDataChannel[0].nRowStep = (uint)stride;
                    imageDataInfo.stDataChannel[0].nSize = (uint)(stride * imageHeight.I);
                    imageDataInfo.stDataChannel[0].nLen = (uint)(imageWidth.I * imageHeight.I);
                    Marshal.Copy(imagePointer, imageDataInfo.stDataChannel[0].arrDataBytes, 0, stride * imageHeight.I);
                    image.InitImage((uint)imageWidth.I, (uint)imageHeight.I, MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08, imageDataInfo);
                }
                //如果是三通道
                else if (channels.I == 3)
                {
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    MVD_IMAGE_DATA_INFO imageDataInfo = new MVD_IMAGE_DATA_INFO();
                    imageDataInfo.stDataChannel = new MVD_DATA_CHANNEL_INFO[4];
                    imageDataInfo.stDataChannel[0] = new MVD_DATA_CHANNEL_INFO();
                    imageDataInfo.stDataChannel[0].arrDataBytes = new byte[stride * imageHeight.I * 3];
                    imageDataInfo.stDataChannel[0].nRowStep = (uint)stride;
                    imageDataInfo.stDataChannel[0].nSize = (uint)(stride * imageHeight.I * 3);
                    imageDataInfo.stDataChannel[0].nLen = (uint)(imageWidth.I * imageHeight.I * 3);
                    HTuple redChannel;
                    HTuple greenChannel;
                    HTuple blueChannel;
                    HOperatorSet.GetImagePointer3(hImageObj, out redChannel, out greenChannel, out blueChannel, out imageType, out imageWidth, out imageHeight);
                    byte[] imageRedBuffer = new byte[stride * imageHeight.I];
                    byte[] imageGreenBuffer = new byte[stride * imageHeight.I];
                    byte[] imageBlueBuffer = new byte[stride * imageHeight.I];
                    Marshal.Copy(redChannel.IP, imageRedBuffer, 0, imageRedBuffer.Length);
                    Marshal.Copy(greenChannel.IP, imageGreenBuffer, 0, imageGreenBuffer.Length);
                    Marshal.Copy(blueChannel.IP, imageBlueBuffer, 0, imageBlueBuffer.Length);
                    for (int row = 0; row < imageHeight.I; row++)
                    {
                        for (int col = 0, index = 0; col < imageWidth.I; col++, index += 3)
                        {
                            imageDataInfo.stDataChannel[0].arrDataBytes[index] = imageRedBuffer[row * imageWidth + col];
                            imageDataInfo.stDataChannel[0].arrDataBytes[index + 1] = imageGreenBuffer[row * imageWidth + col];
                            imageDataInfo.stDataChannel[0].arrDataBytes[index + 2] = imageBlueBuffer[row * imageWidth + col];
                        }
                    }
                    image.InitImage((uint)imageWidth.I, (uint)imageHeight.I, MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3, imageDataInfo);
                }
                else
                {
                    hImageObj?.Dispose();
                    throw new Exception("不支持单通道,三通道以外的图像");
                }
            }
            else
            {
                hImageObj?.Dispose();
                throw new Exception("不支持8bit以外的位深度图像");
            }
        }
        else
        {
            hImageObj?.Dispose();
            throw new Exception("HObject非图像类型对象");
        }
        return image;
    }
    catch (Exception ex)
    {
        hImageObj?.Dispose();
        throw new Exception(ex.Message);
    }
}
public static HObject CMvdImageToHalconImage(CMvdImage image)
{
    IntPtr imagePointer = IntPtr.Zero;
    IntPtr redChannel = IntPtr.Zero;
    IntPtr greenChannel = IntPtr.Zero;
    IntPtr blueChannel = IntPtr.Zero;
    try
    {
        HObject imageObj = new HObject();
        HTuple width = image.Width;
        HTuple height = image.Height;
        if (image.PixelFormat == MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08)
        {
            imagePointer = Marshal.AllocHGlobal(image.GetImageData(0).arrDataBytes.Length);
            Marshal.Copy(image.GetImageData(0).arrDataBytes, 0, imagePointer, image.GetImageData(0).arrDataBytes.Length);
            HOperatorSet.GenImage1(out imageObj, "byte", width, height, imagePointer);
        }
        else if (image.PixelFormat == MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3)
        {
            int stride = width;
            if (stride % 4 != 0)
            {
                stride += 4 - stride % 4;
            }
            byte[] imageRedBuffer = new byte[stride * height.I];
            byte[] imageGreenBuffer = new byte[stride * height.I];
            byte[] imageBlueBuffer = new byte[stride * height.I];
            for (int row = 0; row < height.I; row++)
            {
                for (int col = 0, index = 0; col < width.I; col++, index += 3)
                {
                    imageRedBuffer[row * width.I + col] = image.GetImageData(0).arrDataBytes[index];
                    imageGreenBuffer[row * width.I + col] = image.GetImageData(0).arrDataBytes[index + 1];
                    imageBlueBuffer[row * width.I + col] = image.GetImageData(0).arrDataBytes[index + 2];
                }
            }
            HOperatorSet.GenImage3(
                out imageObj,
                "byte",
                width,
                height,
                Marshal.UnsafeAddrOfPinnedArrayElement(imageRedBuffer, 0),
                Marshal.UnsafeAddrOfPinnedArrayElement(imageGreenBuffer, 0),
                Marshal.UnsafeAddrOfPinnedArrayElement(imageBlueBuffer, 0));
        }
        return imageObj;
    }
    catch (Exception ex)
    {
        Marshal.FreeHGlobal(imagePointer);
        Marshal.FreeHGlobal(redChannel);
        Marshal.FreeHGlobal(greenChannel);
        Marshal.FreeHGlobal(blueChannel);
        throw new Exception(ex.Message);
    }
}

5 流程输出(ImageBaseData_V2)转Halcon图像

public static HObject ImageBaseDataV2ToHalconImage(ImageBaseData_V2 image)
{
    try
    {
        HObject imageObj = new HObject();
        HTuple width = image.Width;
        HTuple height = image.Height;
        if (image.Pixelformat == VMPixelFormat.VM_PIXEL_MONO_08)
        {
            HOperatorSet.GenImage1(out imageObj, "byte", width, height, image.ImageData);
        }
        else if (image.Pixelformat == VMPixelFormat.VM_PIXEL_RGB24_C3)
        {
            int stride = width.I;
            if (stride % 4 != 0)
            {
                stride += 4 - stride % 4;
            }
            byte[] imageRedBuffer = new byte[stride * height.I];
            byte[] imageGreenBuffer = new byte[stride * height.I];
            byte[] imageBlueBuffer = new byte[stride * height.I];
            byte[] imageBuffer = new byte[stride * height.I * 3];
            Marshal.Copy(image.ImageData, imageBuffer, 0, imageBuffer.Length);
            for (int row = 0; row < height.I; row++)
            {
                for (int col = 0, index = 0; col < width.I; col++, index += 3)
                {
                    imageRedBuffer[row * width.I + col] = imageBuffer[index];
                    imageGreenBuffer[row * width.I + col] = imageBuffer[index + 1];
                    imageBlueBuffer[row * width.I + col] = imageBuffer[index + 2];
                }
            }
            HOperatorSet.GenImage3(
                out imageObj,
                "byte",
                width,
                height,
                Marshal.UnsafeAddrOfPinnedArrayElement(imageRedBuffer, 0),
                Marshal.UnsafeAddrOfPinnedArrayElement(imageGreenBuffer, 0),
                Marshal.UnsafeAddrOfPinnedArrayElement(imageBlueBuffer, 0));
        }
        return imageObj;
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }
}

6 halcon图像与脚本图像(ImageData)互转

public static ImageData HalconImageToImageData(HObject hImageObj)
{
    try
    {
        ImageData imageData = new ImageData();
        HTuple imageWidth = 0;
        HTuple imageHeight = 0;
        HTuple objClass = hImageObj.GetObjClass();
        if (objClass.S.Equals("image"))
        {
            HTuple imageType;
            HOperatorSet.GetImageType(hImageObj, out imageType);
            if (imageType.S.Equals("byte"))
            {
                //获取图像通道数
                HTuple channels = 0;
                HOperatorSet.CountChannels(hImageObj, out channels);
                //如果是单通道
                if (channels.I == 1)
                {
                    HTuple imagePointer;
                    HOperatorSet.GetImagePointer1(hImageObj, out imagePointer, out imageType, out imageWidth, out imageHeight);
                    imageData.Width = imageWidth.I;
                    imageData.Heigth = imageHeight.I;
                    imageData.PixelFormat = ImagePixelFormate.MONO8;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    imageData.Buffer = new byte[stride * imageHeight.I];
                    Marshal.Copy(imagePointer, imageData.Buffer, 0, stride * imageHeight.I);
                }
                //如果是三通道
                else if (channels.I == 3)
                {
                    HTuple redChannel;
                    HTuple greenChannel;
                    HTuple blueChannel;
                    HOperatorSet.GetImagePointer3(hImageObj, out redChannel, out greenChannel, out blueChannel, out imageType, out imageWidth, out imageHeight);
                    imageData.Width = imageWidth.I;
                    imageData.Heigth = imageHeight.I;
                    imageData.PixelFormat = ImagePixelFormate.RGB24;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    imageData.Buffer = new byte[stride * imageHeight.I * 3];
                    byte[] imageRedBuffer = new byte[stride * imageHeight.I];
                    byte[] imageGreenBuffer = new byte[stride * imageHeight.I];
                    byte[] imageBlueBuffer = new byte[stride * imageHeight.I];
                    Marshal.Copy(redChannel.IP, imageRedBuffer, 0, imageRedBuffer.Length);
                    Marshal.Copy(greenChannel.IP, imageGreenBuffer, 0, imageGreenBuffer.Length);
                    Marshal.Copy(blueChannel.IP, imageBlueBuffer, 0, imageBlueBuffer.Length);
                    for (int row = 0; row < imageHeight.I; row++)
                    {
                        for (int col = 0, index = 0; col < imageWidth.I; col++, index += 3)
                        {
                            imageData.Buffer[index] = imageRedBuffer[row * imageWidth + col];
                            imageData.Buffer[index + 1] = imageGreenBuffer[row * imageWidth + col];
                            imageData.Buffer[index + 2] = imageBlueBuffer[row * imageWidth + col];
                        }
                    }
                }
                else
                {
                    hImageObj?.Dispose();
                    throw new Exception("不支持单通道,三通道以外的图像");
                }
            }
            else
            {
                hImageObj?.Dispose();
                throw new Exception("不支持8bit以外的位深度图像");
            }
        }
        else
        {
            hImageObj?.Dispose();
            throw new Exception("HObject非图像类型对象");
        }
        return imageData;
    }
    catch (Exception ex)
    {
        hImageObj?.Dispose();
        throw new Exception(ex.Message);
    }
}
public static HObject ImageDataToHalconImage(ImageData image)
{
    IntPtr imagePointer = IntPtr.Zero;
    IntPtr redChannel = IntPtr.Zero;
    IntPtr greenChannel = IntPtr.Zero;
    IntPtr blueChannel = IntPtr.Zero;
    try
    {
        HObject imageObj = new HObject();
        HTuple width = image.Width;
        HTuple height = image.Heigth;
        if (image.PixelFormat == ImagePixelFormate.MONO8)
        {
            imagePointer = Marshal.AllocHGlobal(image.Buffer.Length);
            Marshal.Copy(image.Buffer, 0, imagePointer, image.Buffer.Length);
            HOperatorSet.GenImage1(out imageObj, "byte", width, height, imagePointer);
        }
        else if (image.PixelFormat == ImagePixelFormate.RGB24)
        {
            byte[] imageRedBuffer = new byte[image.Buffer.Length / 3];
            byte[] imageGreBuffer = new byte[image.Buffer.Length / 3];
            byte[] imageBluBuffer = new byte[image.Buffer.Length / 3];
            int index = 0;
            for (int i = 0; i < image.Buffer.Length; index++, i += 3)
            {
                imageRedBuffer[index] = image.Buffer[i];
                imageGreBuffer[index] = image.Buffer[i + 1];
                imageBluBuffer[index] = image.Buffer[i + 2];
            }
            redChannel = Marshal.AllocHGlobal(imageRedBuffer.Length);
            greenChannel = Marshal.AllocHGlobal(imageGreBuffer.Length);
            blueChannel = Marshal.AllocHGlobal(imageBluBuffer.Length);
            Marshal.Copy(imageRedBuffer, 0, redChannel, imageRedBuffer.Length);
            Marshal.Copy(imageGreBuffer, 0, greenChannel, imageGreBuffer.Length);
            Marshal.Copy(imageBluBuffer, 0, blueChannel, imageBluBuffer.Length);
            HOperatorSet.GenImage3(out imageObj, "byte", width, height, redChannel, greenChannel, blueChannel);
        }
        return imageObj;
    }
    catch (Exception ex)
    {
        Marshal.FreeHGlobal(imagePointer);
        Marshal.FreeHGlobal(redChannel);
        Marshal.FreeHGlobal(greenChannel);
        Marshal.FreeHGlobal(blueChannel);
        throw new Exception(ex.Message);
    }
}

问题根因
不熟悉Halcon图像转换为其它类型

3.6 流程图像与算子图像互转

描述
环境:VM4.2 + VS2013及以上
现象:流程图像与算子图像互转
解答
VM SDK开发中流程输入输出图像都是ImageBaseData_V2,算子SDK开发中算子输入输出图像都是CmvdImage,两者可以实现互转。
1 流程图像转算子图像

public CMvdImage ImageBaseData_V2ToCMvdImage(ImageBaseData_V2 ImageBaseDataV2)
{
    VisionDesigner.CMvdImage cmvdImage = new VisionDesigner.CMvdImage();
    VisionDesigner.MVD_IMAGE_DATA_INFO stImageData = new VisionDesigner.MVD_IMAGE_DATA_INFO();
    if (VMPixelFormat.VM_PIXEL_MONO_08 == ImageBaseDataV2.Pixelformat)
    {
        stImageData.stDataChannel[0].nRowStep = (uint)ImageBaseDataV2.Width;
        stImageData.stDataChannel[0].nLen = (uint)(ImageBaseDataV2.Width * ImageBaseDataV2.Height);
        stImageData.stDataChannel[0].nSize = (uint)(ImageBaseDataV2.Width * ImageBaseDataV2.Height);
        byte[] m_BufForDriver1 = new byte[ImageBaseDataV2.Width * ImageBaseDataV2.Height];
        //数据Copy
        Marshal.Copy(ImageBaseDataV2.ImageData, m_BufForDriver1, 0, ((int)ImageBaseDataV2.Width * ImageBaseDataV2.Height));
        stImageData.stDataChannel[0].arrDataBytes = m_BufForDriver1;
        //初始化CMvdImage
        cmvdImage.InitImage((uint)ImageBaseDataV2.Width, (uint)ImageBaseDataV2.Height, MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08, stImageData);
    }
    else if (VMPixelFormat.VM_PIXEL_RGB24_C3 == ImageBaseDataV2.Pixelformat)
    {
        stImageData.stDataChannel[0].nRowStep = (uint)ImageBaseDataV2.Width * 3;
        stImageData.stDataChannel[0].nLen = (uint)(ImageBaseDataV2.Width * ImageBaseDataV2.Height * 3);
        stImageData.stDataChannel[0].nSize = (uint)(ImageBaseDataV2.Width * ImageBaseDataV2.Height * 3);
        byte[] m_BufForDriver1 = new byte[3 * (ImageBaseDataV2.Width * ImageBaseDataV2.Height)];
        //数据Copy
        Marshal.Copy(ImageBaseDataV2.ImageData, m_BufForDriver1, 0, ((int)(ImageBaseDataV2.Width * ImageBaseDataV2.Height) * 3));
        stImageData.stDataChannel[0].arrDataBytes = m_BufForDriver1;
        //初始化CMvdImage
        cmvdImage.InitImage((uint)ImageBaseDataV2.Width, (uint)ImageBaseDataV2.Height, MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3, stImageData);
    }
    return cmvdImage;
}

2 算子图像转流程图像

public ImageBaseData_V2 CMvdImageToImageBaseData_V2(CMvdImage cmvdImage)
{
    VM.PlatformSDKCS.ImageBaseData_V2 ImageBaseDataV2 = null;
    if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 == cmvdImage.PixelFormat)
    {
        var cmvdImageData = cmvdImage.GetImageData();
        IntPtr imagedata = Marshal.AllocHGlobal(cmvdImageData.stDataChannel[0].arrDataBytes.Length);
        Marshal.Copy(cmvdImageData.stDataChannel[0].arrDataBytes, 0, imagedata, cmvdImageData.stDataChannel[0].arrDataBytes.Length);
        ImageBaseDataV2 = new ImageBaseData_V2(imagedata, (uint)cmvdImageData.stDataChannel[0].arrDataBytes.Length, (int)cmvdImage.Width, (int)cmvdImage.Height, VMPixelFormat.VM_PIXEL_MONO_08);
        //使用结束后需要手动释放
        //Marshal.FreeHGlobal(imagedata);
        //imagedata = IntPtr.Zero;
    }
    else if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cmvdImage.PixelFormat)
    {

        var cmvdImageData = cmvdImage.GetImageData();
        IntPtr imagedata = Marshal.AllocHGlobal(cmvdImageData.stDataChannel[0].arrDataBytes.Length);
        Marshal.Copy(cmvdImageData.stDataChannel[0].arrDataBytes, 0, imagedata, cmvdImageData.stDataChannel[0].arrDataBytes.Length);
        ImageBaseDataV2 = new ImageBaseData_V2(imagedata, (uint)cmvdImageData.stDataChannel[0].arrDataBytes.Length, (int)cmvdImage.Width, (int)cmvdImage.Height, VMPixelFormat.VM_PIXEL_RGB24_C3);
        //使用结束后需要手动释放
        //Marshal.FreeHGlobal(imagedata);
        //imagedata = IntPtr.Zero;
    }
    return ImageBaseDataV2;
}

问题根因
不熟悉流程图像与算子图像互转

3.7 图像转换扫盲篇(C++)

描述
环境:VM4.2 + VS2013及以上
现象:有哪些图像类型可以进行转换?
解答
1 图像格式一览
除了QImage、Mat和Halcon中的图像类型,在VM和开发(二次开发包含三种:VM SDK开发、算子SDK开发、算法模块开发)中涉及的图像类型如下:
相机:图像数据流(此处图像数据流类型是MyCamera.MV_FRAME_OUT,是来自MvCameraControl.Net.dll,即海康机器人工业相机SDK,在MVS SDK和算子SDK中都有这个dll;算子SDK的MVDCamera.Net.dll也可以进行相机取流,它是对MvCameraControl.Net.dll的二次封装,用MVDCamera.Net.dll时,图像数据流类型是IMvdImage);
VM:脚本输入图像(图像类型是ImageData,是C#中图像类型);
VM SDK:流程输入图像(IoImage)、Group输入图像(IoImage)、图像源SDK输入图像(ImageBaseData)、模块输入图像(ImageBaseData);
算子SDK:输入图像(IMvdImage);
算法模块:输入图像(HKA_IMAGE)。
2 图像类型转换(含单通道和三通道图像)三通道的Mat为BGR,三通道QImage、VM和二次开发为RGB,针对常用图像转换场景,列举如下(见3.8-3.13)。篇幅所致,后续每种转换用函数表达,函数输入某种图像类型,返回某种图像类型。

3.8 相机采图转流程输入、Group输入、图像源SDK输入、模块输入、算子输入图像

描述
环境:VM4.2 + VS2013及以上
现象:相机采图转换成其他图像类型
解答
相机采图(MyCamera.MV_FRAME_OUT)转换为流程输入图像、Group输入图像、图像源SDK输入图像、模块输入图像、算子输入图像。
1相机采图转流程输入(IoImage)、Group输入(IoImage)

IoImage MV_FRAME_OUTToProcedureIoImage(MV_FRAME_OUT stImageInfo)
{
	// TODO: 在此处添加实现代码.
	IoImage ioImage{};
	unsigned char* m_pSaveImageBuf = NULL;//建议在头文件声明,控制释放时机防止内存泄漏,写在此处为了方便参考
	m_pSaveImageBuf = (unsigned char*)malloc(sizeof(unsigned char) * stImageInfo.stFrameInfo.nFrameLen);
	memcpy(m_pSaveImageBuf, stImageInfo.pBufAddr, stImageInfo.stFrameInfo.nFrameLen);

	ioImage.stImage.Width = stImageInfo.stFrameInfo.nWidth;
	ioImage.stImage.Height = stImageInfo.stFrameInfo.nHeight;
	ioImage.stImage.DataLen = stImageInfo.stFrameInfo.nFrameLen;
	ioImage.stImage.ImageData = m_pSaveImageBuf;
	if (stImageInfo.stFrameInfo.enPixelType == PixelType_Gvsp_Mono8)
	{
		ioImage.stImage.Pixelformat = MvdPixelFormat::MVD_PIXEL_MONO_08;
	}
	else if (stImageInfo.stFrameInfo.enPixelType == PixelType_Gvsp_RGB8_Packed)
	{
		ioImage.stImage.Pixelformat = MvdPixelFormat::MVD_PIXEL_RGB_RGB24_C3;
	}
	return ioImage;
}

2相机采图转图像源SDK输入(ImageBaseData)、模块输入(ImageBaseData)

ImageBaseData MV_FRAME_OUTToImageBaseData(MV_FRAME_OUT stImageInfo)
{
	// TODO: 在此处添加实现代码.
	ImageBaseData imageBaseData{};
	unsigned char* m_pSaveImageBuf = NULL;//建议在头文件声明,控制释放时机防止内存泄漏,写在此处为了方便参考
	m_pSaveImageBuf = (unsigned char*)malloc(sizeof(unsigned char) * stImageInfo.stFrameInfo.nFrameLen);
	memcpy(m_pSaveImageBuf, stImageInfo.pBufAddr, stImageInfo.stFrameInfo.nFrameLen);

	imageBaseData.Width = stImageInfo.stFrameInfo.nWidth;
	imageBaseData.Height = stImageInfo.stFrameInfo.nHeight;
	imageBaseData.DataLen = stImageInfo.stFrameInfo.nFrameLen;
	imageBaseData.ImageData = m_pSaveImageBuf;
	if (stImageInfo.stFrameInfo.enPixelType == PixelType_Gvsp_Mono8)
	{
		imageBaseData.Pixelformat = MvdPixelFormat::MVD_PIXEL_MONO_08;
	}
	else if (stImageInfo.stFrameInfo.enPixelType == PixelType_Gvsp_RGB8_Packed)
	{
		imageBaseData.Pixelformat = MvdPixelFormat::MVD_PIXEL_RGB_RGB24_C3;
	}

	return imageBaseData;
}

3相机采图转算子输入(IMvdImage)

IMvdImage* MV_FRAME_OUTToIMvdImage(MV_FRAME_OUT stImageInfo)
{
	// TODO: 在此处添加实现代码.
	IMvdImage* iMvdImage = NULL;
	unsigned char* m_pSaveImageBuf = NULL;//建议在头文件声明,控制释放时机防止内存泄漏,写在此处为了方便参考
	m_pSaveImageBuf = (unsigned char*)malloc(sizeof(unsigned char) * stImageInfo.stFrameInfo.nFrameLen);
	memcpy(m_pSaveImageBuf, stImageInfo.pBufAddr, stImageInfo.stFrameInfo.nFrameLen);
	MVD_IMAGE_DATA_INFO stImageData{ };

	if (stImageInfo.stFrameInfo.enPixelType == PixelType_Gvsp_Mono8)
	{
		stImageData.stDataChannel[0].nRowStep = stImageInfo.stFrameInfo.nWidth;
		stImageData.stDataChannel[0].nLen = stImageInfo.stFrameInfo.nFrameLen;
		stImageData.stDataChannel[0].nSize = stImageInfo.stFrameInfo.nFrameLen;
		stImageData.stDataChannel[0].pData = m_pSaveImageBuf;
		iMvdImage->InitImage(stImageInfo.stFrameInfo.nWidth, stImageInfo.stFrameInfo.nHeight, VisionDesigner::_MVD_PIXEL_FORMAT_::MVD_PIXEL_MONO_08, stImageData);
	}
	else if (stImageInfo.stFrameInfo.enPixelType == PixelType_Gvsp_RGB8_Packed)
	{
		stImageData.stDataChannel[0].nRowStep = stImageInfo.stFrameInfo.nWidth*3;
		stImageData.stDataChannel[0].nLen = stImageInfo.stFrameInfo.nFrameLen;
		stImageData.stDataChannel[0].nSize = stImageInfo.stFrameInfo.nFrameLen;
		stImageData.stDataChannel[0].pData = m_pSaveImageBuf;
		iMvdImage->InitImage(stImageInfo.stFrameInfo.nWidth, stImageInfo.stFrameInfo.nHeight, VisionDesigner::_MVD_PIXEL_FORMAT_::MVD_PIXEL_BGR_BGR24_C3, stImageData);
	}

	return iMvdImage;
}

问题根因
不熟悉相机采图转换为其它类型

3.9 QImage转流程输入、Group输入、图像源SDK输入、模块输入、算子输入、流程输出图像

描述
环境:VM4.2 + VS2013及以上
现象:QImage转换成其他图像类型
解答
QImage转换为流程输入图像、Group输入图像、图像源SDK输入图像、模块输入图像、算子输入图像,流程输出图像转换为Bitmap。
1 QImage转流程输入(IoImage)、Group输入(IoImage)

IoImage QImageToIoImage(QImage qImage)
{
    QString strReMsg = "";
    IoImage ioImage;
    switch (qImage.format())
    {
    case QImage::Format_Indexed8:
        ioImage.stImage.Width=qImage.width();
        ioImage.stImage.Height=qImage.height();
        ioImage.stImage.DataLen=qImage.sizeInBytes();
        ioImage.stImage.Pixelformat=_MvdPixelFormat_::MVD_PIXEL_MONO_08;
        ioImage.stImage.ImageData=(void *)qImage.constBits();
        //ioImage.stImage.ImageData=qImage.data_ptr();
        //QImage(ioImage.stImage.ImageData,ioImage.stImage.Width,ioImage.stImage.Width,QImage::Format_RGB888);
        break;       
    case QImage::Format_RGB888:
        ioImage.stImage.Width=qImage.width();
        ioImage.stImage.Height=qImage.height();
        ioImage.stImage.DataLen=qImage.sizeInBytes();
        ioImage.stImage.Pixelformat=_MvdPixelFormat_::MVD_PIXEL_RGB_RGB24_C3;
        ioImage.stImage.ImageData=(void *)qImage.constBits();
        break;
    }
    strReMsg = "QImageToIoImage s uccess.";
    ui->textEdit->append(strReMsg);
    return ioImage;
}

2 QImage转图像源SDK输入(ImageBaseData)、模块输入(ImageBaseData)

ImageBaseData QImageToImageBaseData(QImage qImage)
{
    ImageBaseData  imageBaseData;
    switch (qImage.format())
    {
    case QImage::Format_Indexed8:
        imageBaseData.Width=qImage.width();
        imageBaseData.Height=qImage.height();
        imageBaseData.DataLen=qImage.sizeInBytes();
        imageBaseData.Pixelformat=_MvdPixelFormat_::MVD_PIXEL_MONO_08;
        imageBaseData.ImageData=(void *)qImage.constBits();
        //ioImage.stImage.ImageData=qImage.data_ptr();
        break;
    case QImage::Format_RGB888:
        imageBaseData.Width=qImage.width();
        imageBaseData.Height=qImage.height();
        imageBaseData.DataLen=qImage.sizeInBytes();
        imageBaseData.Pixelformat=_MvdPixelFormat_::MVD_PIXEL_RGB_RGB24_C3;
        imageBaseData.ImageData=(void *)qImage.constBits();
        break;
    }
    return imageBaseData;
}

3 Qimage与算子图像(IMvdImage)互转

IMvdImage* QImageToIMvdImage(QImage qImage)
{
    IMvdImage* iMvdImage;
    CreateImageInstance(&iMvdImage);
    MVD_IMAGE_DATA_INFO stImageData;
    switch (qImage.format())
    {
    case QImage::Format_Indexed8:
        stImageData.stDataChannel[0].nRowStep = qImage.width();
        stImageData.stDataChannel[0].nLen = qImage.sizeInBytes();
        stImageData.stDataChannel[0].nSize = qImage.sizeInBytes();
        stImageData.stDataChannel[0].pData = (unsigned char*)qImage.constBits();
        iMvdImage->InitImage(qImage.width(), qImage.height(),MVD_PIXEL_FORMAT::MVD_PIXEL_MONO_08, stImageData);
        break;
    case QImage::Format_RGB888:
        stImageData.stDataChannel[0].nRowStep = qImage.width()*3;
        stImageData.stDataChannel[0].nLen = qImage.sizeInBytes();
        stImageData.stDataChannel[0].nSize = qImage.sizeInBytes();
        stImageData.stDataChannel[0].pData = (unsigned char*)qImage.constBits();
        iMvdImage->InitImage(qImage.width(), qImage.height(),MVD_PIXEL_FORMAT::MVD_PIXEL_RGB_RGB24_C3, stImageData);
        break;
    }
    return iMvdImage;
}

//算子转QImage
QImage IMvdImageToQImage(IMvdImage * iMvdImage)
{
    if(iMvdImage->GetPixelFormat() == MVD_PIXEL_FORMAT::MVD_PIXEL_MONO_08)
    {
        //QImage qImage((const uchar*)iMvdImage->GetImageData(0)->pData,iMvdImage->GetWidth(),iMvdImage->GetHeight(),iMvdImage->GetImageData(0)->nLen/iMvdImage->GetHeight(),QImage::Format_Indexed8);
        //QImage qImage(iMvdImage->GetImageData(0)->pData,iMvdImage->GetWidth(),iMvdImage->GetHeight(),iMvdImage->GetImageData(0)->nLen/iMvdImage->GetHeight(),QImage::Format_Indexed8);
        QImage qImage((const uchar*)iMvdImage->GetImageData(0)->pData,iMvdImage->GetWidth(),iMvdImage->GetHeight(),QImage::Format_Grayscale8);//Format_Indexed8
        return qImage;
    }
    if(iMvdImage->GetPixelFormat() == MVD_PIXEL_FORMAT::MVD_PIXEL_RGB_RGB24_C3)
    {
        QImage qImage((const uchar*)iMvdImage->GetImageData(0)->pData,iMvdImage->GetWidth(),iMvdImage->GetHeight(),QImage::Format_RGB888);
        return qImage;
    }
}

4 流程输出(IoImage)转QImage

QImage IoImageToQImage(IoImage inIoImage)
{
    if(inIoImage.stImage.Pixelformat == _MvdPixelFormat_::MVD_PIXEL_MONO_08)
    {
        QImage qImage((const uchar*)inIoImage.stImage.ImageData,inIoImage.stImage.Width,inIoImage.stImage.Height,QImage::Format_Grayscale8);
        return qImage;
    }
    if(inIoImage.stImage.Pixelformat == _MvdPixelFormat_::MVD_PIXEL_RGB_RGB24_C3)
    {
        QImage qImage((const uchar*)inIoImage.stImage.ImageData,inIoImage.stImage.Width,inIoImage.stImage.Height,QImage::Format_RGB888);
        return qImage;
    }
}

问题根因
不熟悉QImage转换为其它类型

3.10 Mat与流程输入、Group输入、图像源SDK输入、模块输入、算子输入、算子输出、流程输出

描述
环境:VM4.2 + VS2013及以上
现象:Mat转换成其他图像类型
解答
Mat转换为流程输入图像、Group输入图像、图像源SDK输入图像、模块输入图像、算子输入图像,算子输出图像转Mat,流程输出图像转换为Mat。
1 Mat转流程输入(IoImage)、Group输入(IoImage)

IoImage MatToProcedureInputImage(Mat matInputImg)
{
	if (matInputImg.empty())
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_PARAMETER_ILLEGAL);
	}
	if ((CV_8UC1 != matInputImg.type()) && (CV_8UC3 != matInputImg.type()))
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_SUPPORT);
	}

	IoImage  m_pIoImage{};
	uint dataLen = (uint)(matInputImg.cols * matInputImg.rows * matInputImg.channels());
	CString strReMsg = _T("");
	try
	{
		if (CV_8UC1 == matInputImg.type())
		{
			m_pIoImage.stImage.Width = matInputImg.cols;
			m_pIoImage.stImage.Width = matInputImg.cols;
			m_pIoImage.stImage.Height = matInputImg.rows;
			m_pIoImage.stImage.DataLen = dataLen;
			m_pIoImage.stImage.Pixelformat = _MvdPixelFormat_::MVD_PIXEL_MONO_08;
			m_pIoImage.stImage.ImageData = matInputImg.ptr(0);
		}
		else if (CV_8UC3 == matInputImg.type())
		{
			cv::cvtColor(matInputImg, matInputImg, CV_BGR2RGB);
			m_pIoImage.stImage.Width = matInputImg.cols;
			m_pIoImage.stImage.Height = matInputImg.rows;
			m_pIoImage.stImage.DataLen = dataLen;
			m_pIoImage.stImage.Pixelformat = _MvdPixelFormat_::MVD_PIXEL_RGB_RGB24_C3;
			m_pIoImage.stImage.ImageData = matInputImg.ptr(0);
		}
	}
	catch (CVmException e)
	{
		strReMsg.Format(_T("%x"), e.GetErrorCode());
		strReMsg = _T("0x") + strReMsg + _T(" == SaveProcedureToFile()");
	}

	return m_pIoImage;
}

2 Mat转图像源SDK输入(ImageBaseData)、模块输出(ImageBaseData)

ImageBaseData MatToImageBaseData(Mat matInputImg)
{
	if (matInputImg.empty())
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_PARAMETER_ILLEGAL);
	}
	if ((CV_8UC1 != matInputImg.type()) && (CV_8UC3 != matInputImg.type()))
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_SUPPORT);
	}

	ImageBaseData  m_pImageBaseData{};
	uint dataLen = (uint)(matInputImg.cols * matInputImg.rows * matInputImg.channels());
	CString strReMsg = _T("");
	try
	{
		if (CV_8UC1 == matInputImg.type())
		{
			m_pImageBaseData.Width = matInputImg.cols;
			m_pImageBaseData.Height = matInputImg.rows;
			m_pImageBaseData.DataLen = dataLen;
			m_pImageBaseData.Pixelformat = _MvdPixelFormat_::MVD_PIXEL_MONO_08;
			m_pImageBaseData.ImageData = matInputImg.ptr(0);
		}
		else if (CV_8UC3 == matInputImg.type())
		{
			cv::cvtColor(matInputImg, matInputImg, CV_BGR2RGB);
			m_pImageBaseData.Width = matInputImg.cols;
			m_pImageBaseData.Height = matInputImg.rows;
			m_pImageBaseData.DataLen = dataLen;
			m_pImageBaseData.Pixelformat = _MvdPixelFormat_::MVD_PIXEL_RGB_RGB24_C3;
			m_pImageBaseData.ImageData = matInputImg.ptr(0);
		}
	}
	catch (CVmException e)
	{
		strReMsg.Format(_T("%x"), e.GetErrorCode());
		strReMsg = _T("0x") + strReMsg + _T(" == SaveProcedureToFile()");
	}

	return m_pImageBaseData;
}

3 Mat与算子图像(IMvdImage)互转

IMvdImage* MatToIMvdImage(Mat& matInputImg)
{
	if (matInputImg.empty())
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_PARAMETER_ILLEGAL);
	}
	if ((CV_8UC1 != matInputImg.type()) && (CV_8UC3 != matInputImg.type()))
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_SUPPORT);
	}

	IMvdImage* pMvdImg = NULL;
	uint dataLen = (uint)(matInputImg.cols * matInputImg.rows * matInputImg.channels());
	try
	{
		int nRet = CreateImageInstance(&pMvdImg);
		if (MVD_OK != nRet)
		{
			throw IMVDException(MVD_MODUL_IMAGE, nRet, "Failed to create image instance.");
		}
		if (CV_8UC1 == matInputImg.type())
		{
			MVD_IMAGE_DATA_INFO stImageData{ };
			stImageData.stDataChannel[0].nRowStep = (uint)matInputImg.cols;
			stImageData.stDataChannel[0].nLen = dataLen;
			stImageData.stDataChannel[0].nSize = dataLen;
			stImageData.stDataChannel[0].pData = matInputImg.ptr(0);
			pMvdImg->InitImage((uint)matInputImg.cols, (uint)matInputImg.rows, VisionDesigner::_MVD_PIXEL_FORMAT_::MVD_PIXEL_MONO_08, stImageData);

		}
		else if (CV_8UC3 == matInputImg.type())
		{
			cv::cvtColor(matInputImg, matInputImg, CV_BGR2RGB);
			MVD_IMAGE_DATA_INFO stImageData{ };
			stImageData.stDataChannel[0].nRowStep = (uint)matInputImg.cols*matInputImg.channels();
			stImageData.stDataChannel[0].nLen = dataLen;
			stImageData.stDataChannel[0].nSize = dataLen;
			stImageData.stDataChannel[0].pData = matInputImg.ptr(0);
			pMvdImg->InitImage((uint)matInputImg.cols, (uint)matInputImg.rows, VisionDesigner::_MVD_PIXEL_FORMAT_::MVD_PIXEL_RGB_RGB24_C3, stImageData);
		}
	}
	catch (IMVDException &ex)
	{
		if (NULL != pMvdImg)
		{
			DestroyImageInstance(pMvdImg);
			pMvdImg = NULL;
		}
		throw ex;
	}

	return pMvdImg;
}

Mat IMvdImageToMat(IMvdImage* pMvdImg)
{
	Mat stMatImg;

	if (NULL == pMvdImg)
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_PARAMETER_ILLEGAL);
	}
	MVD_PIXEL_FORMAT enSrcPixelFormat = pMvdImg->GetPixelFormat();
	if ((VisionDesigner::MVD_PIXEL_FORMAT::MVD_PIXEL_MONO_08 != enSrcPixelFormat) && (VisionDesigner::MVD_PIXEL_FORMAT::MVD_PIXEL_RGB_RGB24_C3 != enSrcPixelFormat))
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_SUPPORT);
	}

	// 根据传入的ImvdImage图像初始化mat
	if (VisionDesigner::MVD_PIXEL_FORMAT::MVD_PIXEL_MONO_08 == enSrcPixelFormat)
	{
		stMatImg.create((int)pMvdImg->GetHeight(), (int)pMvdImg->GetWidth(), CV_8UC1);
	}
	else if (VisionDesigner::MVD_PIXEL_FORMAT::MVD_PIXEL_RGB_RGB24_C3 == enSrcPixelFormat)
	{
		stMatImg.create((int)pMvdImg->GetHeight(), (int)pMvdImg->GetWidth(), CV_8UC3);
	}
	if (stMatImg.empty())
	{
		throw IMVDException(MVD_MODUL_APP, MVD_E_RESOURCE);
	}

	// 上述方式为mat分配的内存一定是连续的
	uchar* pdata = stMatImg.ptr<uchar>(0);
	memcpy(pdata, pMvdImg->GetImageData(0)->pData, pMvdImg->GetImageData(0)->nLen);
	if (CV_8UC3 == stMatImg.type())
	{
		cvtColor(stMatImg, stMatImg, CV_RGB2BGR);
	}

	return stMatImg;
}

4 流程输出(IoImage)转Mat

Mat IoImageToMat(IoImage m_pIoImage)
{
	Mat stMatImg;
	CString strReMsg = _T("");
	try
	{
		MvdPixelFormat srcPixelFormat = m_pIoImage.stImage.Pixelformat;
		if ((VisionMasterSDK::MvdPixelFormat::MVD_PIXEL_MONO_08 != srcPixelFormat) && (VisionMasterSDK::MvdPixelFormat::MVD_PIXEL_RGB_RGB24_C3 != srcPixelFormat))
		{
			throw CVmException(0xE0000503);
		}
		// 根据传入的IoImage图像初始化mat
		if (VisionMasterSDK::MvdPixelFormat::MVD_PIXEL_MONO_08 == srcPixelFormat)
		{
			stMatImg.create((int)m_pIoImage.stImage.Height, (int)m_pIoImage.stImage.Width, CV_8UC1);
		}
		else if (VisionMasterSDK::MvdPixelFormat::MVD_PIXEL_RGB_RGB24_C3 == srcPixelFormat)
		{
			stMatImg.create((int)m_pIoImage.stImage.Height, (int)m_pIoImage.stImage.Width, CV_8UC3);
		}
		if (stMatImg.empty())
		{
			throw IMVDException(MVD_MODUL_APP, MVD_E_RESOURCE);
		}
		// 上述方式为mat分配的内存一定是连续的
		uchar* pdata = stMatImg.ptr<uchar>(0);
		memcpy(pdata, m_pIoImage.stImage.ImageData, m_pIoImage.stImage.DataLen);
		if (CV_8UC3 == stMatImg.type())
		{
			cvtColor(stMatImg, stMatImg, CV_RGB2BGR);
		}
	}
	catch (CVmException e)
	{
		strReMsg.Format(_T("%x"), e.GetErrorCode());
		strReMsg = _T("0x") + strReMsg + _T(" == SaveProcedureToFile()");
	}

	return stMatImg;
}

问题根因
不熟悉Mat转换为其它类型

3.11 Halcon与流程输入、Group输入、图像源SDK输入、模块输入、算子输入、算子输出、流程输出

描述
环境:VM4.2 + VS2013及以上
现象:Halcon转换成其他图像类型
解答
Halcon图像转换为流程输入图像、Group输入图像、图像源SDK输入图像、模块输入图像、算子输入图像,算子输出图像转Halcon图像,流程输出图像转换为Halcon图像。
1 Halcon图像转流程输入(IoImage)、Group输入(IoImage),HImageToImageBaseData函数的实现见“2 Halcon图像转ImageBaseData“

IoImage HImageToIoImage(HImage image)
{
	IoImage ioImage{};
	ImageBaseData imageBaseData = HImageToImageBaseData(image);
	ioImage.stImage = imageBaseData;
	return ioImage;
}

2 Halcon图像转图像源SDK输入(ImageBaseData)、模块输入(ImageBaseData)

ImageBaseData HImageToImageBaseData(HImage image)
{
	ImageBaseData imageBaseData{};
	//获取图像通道位深度信息
	HString bitdepth = image.GetChannelInfo("type", 1);
	assert(!strcmp(bitdepth.Text(), "byte"));
	int channels = image.CountChannels();
	assert(channels == 1 || channels == 3);
	HString type;
	Hlong width, height;
	//单通道
	if (channels == 1)
	{
		void* imagePtr = image.GetImagePointer1(&type, &width, &height);
		imageBaseData.DataLen = width * height;
		imageBaseData.Width = width;
		imageBaseData.Height = height;
		imageBaseData.Pixelformat = MvdPixelFormat::MVD_PIXEL_MONO_08;
		imageBaseData.ImageData = imagePtr;
	}
	//3通道
	if (channels == 3)
	{
		void* imageRedPtr;
		void* imageGreenPtr;
		void* imageBluePtr;
		image.GetImagePointer3(&imageRedPtr, &imageGreenPtr, &imageBluePtr, &type, &width, &height);
		byte* imageRedBuf = new byte[width * height];
		byte* imageGreenBuf = new byte[width * height];
		byte* imageBlueBuf = new byte[width * height];
		memcpy(imageRedBuf, imageRedPtr, width * height);
		memcpy(imageGreenBuf, imageGreenPtr, width * height);
		memcpy(imageBlueBuf, imageBluePtr, width * height);
		byte* imageBuf = new byte[width * height * 3];
		int index = 0;
		for (int row = 0; row < height; row++)
		{
			for (int col = 0; col < width; col++, index += 3)
			{
				imageBuf[index] = imageRedBuf[row * width + col];
				imageBuf[index + 1] = imageGreenBuf[row * width + col];
				imageBuf[index + 2] = imageBlueBuf[row * width + col];
			}
		}
		delete[] imageRedBuf;
		delete[] imageGreenBuf;
		delete[] imageBlueBuf;
		imageBaseData.DataLen = width * height * 3;
		imageBaseData.Width = width;
		imageBaseData.Height = height;
		imageBaseData.Pixelformat = MvdPixelFormat::MVD_PIXEL_RGB_RGB24_C3;
		imageBaseData.ImageData = imageBuf;
	}
	return imageBaseData;
}

3 Halcon图像与算子图像(IMvdImage)互转

IMvdImage* HImageToMvdImage(HImage image)
{
	//获取图像通道位深度信息
	HString bitdepth = image.GetChannelInfo("type", 1);
	assert(!strcmp(bitdepth.Text(), "byte"));
	int channels = image.CountChannels();
	assert(channels == 1 || channels == 3);
	HString type;
	Hlong width, height;
	//单通道
	if (channels == 1)
	{
		IMvdImage* pMvdImage;
		CreateImageInstance(&pMvdImage);
		void* imagePtr = image.GetImagePointer1(&type, &width, &height);
		MVD_IMAGE_DATA_INFO imageDataInfo;
		imageDataInfo.stDataChannel[0].nLen = width * height;
		imageDataInfo.stDataChannel[0].nRowStep = width;
		imageDataInfo.stDataChannel[0].nSize = width * height;
		imageDataInfo.stDataChannel[0].pData = (byte*)imagePtr;
		pMvdImage->InitImage(width, height, MVD_PIXEL_FORMAT::MVD_PIXEL_MONO_08, imageDataInfo);
		return pMvdImage;
	}
	//3通道
	else if (channels == 3)
	{
		IMvdImage* pMvdImage;
		CreateImageInstance(&pMvdImage);
		void* imageRedPtr;
		void* imageGreenPtr;
		void* imageBluePtr;
		image.GetImagePointer3(&imageRedPtr, &imageGreenPtr, &imageBluePtr, &type, &width, &height);
		long size = width * height * 3;
		byte* imageRedBuf = new byte[width * height];
		byte* imageGreenBuf = new byte[width * height];
		byte* imageBlueBuf = new byte[width * height];
		memcpy(imageRedBuf, imageRedPtr, width * height);
		memcpy(imageGreenBuf, imageGreenPtr, width * height);
		memcpy(imageBlueBuf, imageBluePtr, width * height);
		byte* imageBuffer = new byte[size];
		int index = 0;
		for (int row = 0; row < height; row++)
		{
			for (int col = 0; col < width; col++, index += 3)
			{
				imageBuffer[index] = imageRedBuf[row * width + col];
				imageBuffer[index + 1] = imageGreenBuf[row * width + col];
				imageBuffer[index + 2] = imageBlueBuf[row * width + col];
			}
		}
		delete[] imageRedBuf;
		delete[] imageGreenBuf;
		delete[] imageBlueBuf;
		MVD_IMAGE_DATA_INFO imageDataInfo{};
		imageDataInfo.stDataChannel[0].nLen = width * height * 3;
		imageDataInfo.stDataChannel[0].nRowStep = width * 3;
		imageDataInfo.stDataChannel[0].nSize = width * height * 3;
		imageDataInfo.stDataChannel[0].pData = imageBuffer;
		try {
			pMvdImage->InitImage(width, height, MVD_PIXEL_FORMAT::MVD_PIXEL_RGB_RGB24_C3, imageDataInfo);
		}
		catch (IMVDException* ex)
		{
			cout << ex->GetDescription() << ex->GetErrorCode() << endl;
		}
		return pMvdImage;
	}
	else
	{
		return nullptr;
	}
}

HImage MvdImageToHImage(IMvdImage* pMvdImage)
{
	HImage image;
	MVD_IMAGE_DATA_INFO* imageDataInfo = pMvdImage->GetImageData();
	if (pMvdImage->GetPixelFormat() == MVD_PIXEL_FORMAT::MVD_PIXEL_MONO_08)
	{
		image.GenImage1(
			"byte",
			pMvdImage->GetWidth(),
			pMvdImage->GetHeight(),
			imageDataInfo->stDataChannel[0].pData);
	}
	else if (pMvdImage->GetPixelFormat() == MVD_PIXEL_FORMAT::MVD_PIXEL_RGB_RGB24_C3)
	{
		int width = pMvdImage->GetWidth();
		int height = pMvdImage->GetHeight();
		long size = width * height * 3;
		byte* imageRedBuf = new byte[(long)(width * height)];
		byte* imageGreenBuf = new byte[(long)(width * height)];
		byte* imageBlueBuf = new byte[(long)(width * height)];
		byte* imageBuffer = new byte[size];
		memcpy(imageBuffer, pMvdImage->GetImageData()->stDataChannel[0].pData, size);
		int index = 0;
		for (int row = 0; row < height; row++)
		{
			for (int col = 0; col < width; col++, index += 3)
			{
				imageRedBuf[row * width + col] = imageBuffer[index];
				imageGreenBuf[row * width + col] = imageBuffer[index + 1];
				imageBlueBuf[row * width + col] = imageBuffer[index + 2];
			}
		}
		delete[] imageBuffer;
		image.GenImage3(
			"byte",
			pMvdImage->GetWidth(),
			pMvdImage->GetHeight(),
			imageRedBuf,
			imageGreenBuf,
			imageBlueBuf);
	}
	return image;
}

4 流程输出(IoImage)转Halcon图像

HImage IoImageToHImage(IoImage ioImage)
{
	HImage image;
	if (ioImage.stImage.Pixelformat == MvdPixelFormat::MVD_PIXEL_MONO_08)
	{
		image.GenImage1("byte", ioImage.stImage.Width, ioImage.stImage.Height, ioImage.stImage.ImageData);
	}
	if (ioImage.stImage.Pixelformat == MvdPixelFormat::MVD_PIXEL_RGB_RGB24_C3)
	{
		int width = ioImage.stImage.Width;
		int height = ioImage.stImage.Height;
		long size = width * height * 3;
		byte* imageRedBuf = new byte[(long)width * height];
		byte* imageGreenBuf = new byte[(long)width * height];
		byte* imageBlueBuf = new byte[(long)width * height];
		byte* imageBuffer = new byte[size];
		memcpy(imageBuffer, ioImage.stImage.ImageData, size);
		int index = 0;
		for (int row = 0; row < height; row++)
		{
			for (int col = 0; col < width; col++, index += 3)
			{
				imageRedBuf[row * width + col] = imageBuffer[index];
				imageGreenBuf[row * width + col] = imageBuffer[index + 1];
				imageBlueBuf[row * width + col] = imageBuffer[index + 2];
			}
		}
		delete[] imageBuffer;
		image.GenImage3("byte", width, height, imageRedBuf, imageGreenBuf, imageBlueBuf);
	}
	return image;
}

问题根因
不熟悉Halcon图像转换为其它类型

3.12 流程图像与算子图像互转

描述
环境:VM4.2 + VS2013及以上
现象:流程图像与算子图像互转
解答
VM SDK开发中流程输入输出图像都是IoImage,算子SDK开发中算子输入输出图像都是ImvdImage,两者可以实现互转。
1 流程图像转算子图像

IMvdImage* ImageConvert::IoImageToIMvdImage(IoImage ioImage)
{
	// TODO: 在此处添加实现代码.
	IMvdImage* iMvdImage = NULL;
	MVD_IMAGE_DATA_INFO stImageData{ };

	if (ioImage.stImage.Pixelformat == MvdPixelFormat::MVD_PIXEL_MONO_08)
	{
		stImageData.stDataChannel[0].nRowStep = ioImage.stImage.Width;
		stImageData.stDataChannel[0].nLen = ioImage.stImage.DataLen;
		stImageData.stDataChannel[0].nSize = ioImage.stImage.DataLen;
		stImageData.stDataChannel[0].pData = (unsigned char*)ioImage.stImage.ImageData;
		iMvdImage->InitImage(ioImage.stImage.Width, ioImage.stImage.Height, VisionDesigner::_MVD_PIXEL_FORMAT_::MVD_PIXEL_MONO_08, stImageData);
	}
	else if (ioImage.stImage.Pixelformat == MvdPixelFormat::MVD_PIXEL_RGB_RGB24_C3)
	{
		stImageData.stDataChannel[0].nRowStep = ioImage.stImage.Width*3;
		stImageData.stDataChannel[0].nLen = ioImage.stImage.DataLen;
		stImageData.stDataChannel[0].nSize = ioImage.stImage.DataLen;
		stImageData.stDataChannel[0].pData = (unsigned char*)ioImage.stImage.ImageData;
		iMvdImage->InitImage(ioImage.stImage.Width, ioImage.stImage.Height, VisionDesigner::_MVD_PIXEL_FORMAT_::MVD_PIXEL_BGR_BGR24_C3, stImageData);
	}

	return iMvdImage;
}

2 算子图像转流程图像

IoImage ImageConvert::IMvdImageToIoImage(IMvdImage* iMvdImage)
{
	// TODO: 在此处添加实现代码.
	IoImage ioImage{};

	ioImage.stImage.Width = iMvdImage->GetWidth();
	ioImage.stImage.Height = iMvdImage->GetHeight();
	
	ioImage.stImage.ImageData = iMvdImage->GetImageData(0)->pData;//图像数据内存地址是连续的
	if (iMvdImage->GetPixelFormat() == MVD_PIXEL_FORMAT::MVD_PIXEL_MONO_08)
	{
		ioImage.stImage.DataLen = iMvdImage->GetImageData(0)->nLen;
		ioImage.stImage.Pixelformat = MvdPixelFormat::MVD_PIXEL_MONO_08;
	}
	else if (iMvdImage->GetPixelFormat() == MVD_PIXEL_FORMAT::MVD_PIXEL_BGR_BGR24_C3)
	{
		ioImage.stImage.Pixelformat = MvdPixelFormat::MVD_PIXEL_RGB_RGB24_C3;
	}
	return ioImage;
}

问题根因
不熟悉流程图像与算子图像互转

3.13 算法模块图像与Mat、Halcon、算子图像互转的方法

描述
环境:VM4.2 + VS2013及以上
现象:算法模块图像转换成其它类型
解答
算法模块图像与Mat、Halcon图像、算子图像实现互转,自定义算法模块开发时,在C++工程中,算法的图像类型为HKA_IMAGE。
1 HKA_IMAGE与Mat互转

Mat CAlgorithmModule::HKAImageToMat(HKA_IMAGE inputimage)
{
    Mat mat, mat1;
    if (inputimage.format == HKA_IMG_MONO_08)
    {
        mat = Mat(inputimage.height, inputimage.width, CV_8UC1, inputimage.data[0]);
    }
    else if (inputimage.format == HKA_IMG_RGB_RGB24_C3)
    {
        mat1 = Mat(inputimage.height, inputimage.width, CV_8UC3, inputimage.data[0]);
        cvtColor(mat1, mat, COLOR_RGB2BGR);
    }
    return mat;
}



HKA_IMAGE CAlgorithmModule::MatToHKAImage(Mat mat)
{	
	HKA_IMAGE inputimage;
	if (mat.channels() == 1)
	{
		inputimage = { HKA_IMG_MONO_08, 0 };
		inputimage.width = mat.cols;
		inputimage.height = mat.rows;
		inputimage.format = HKA_IMG_MONO_08;
		inputimage.step[0] = mat.cols;
		inputimage.data[0] = (char*)malloc(inputimage.width * inputimage.height);
		if (inputimage.data[0] != NULL)
		{
			memset(inputimage.data[0], 0, inputimage.width * inputimage.height);
			memcpy_s(inputimage.data[0], inputimage.width * inputimage.height, mat.data, inputimage.width * inputimage.height);
		}
	}
	else if (mat.channels() == 3)
	{
		cvtColor(mat, mat, COLOR_BGR2RGB);
		inputimage = { HKA_IMG_RGB_RGB24_C3, 0 };
		inputimage.width = mat.cols;
		inputimage.height = mat.rows;
		inputimage.format = HKA_IMG_RGB_RGB24_C3;
		inputimage.step[0] = mat.cols * 3;
		inputimage.data[0] = (char*)malloc(inputimage.width * inputimage.height * 3);
		if (inputimage.data[0] != NULL)
		{
			memset(inputimage.data[0], 0, inputimage.width * inputimage.height * 3);
			memcpy_s(inputimage.data[0], inputimage.width * inputimage.height * 3, mat.data, inputimage.width * inputimage.height * 3);
		}
	}
	return inputimage;
}

2 HKA_IMAGE与Halcon图像互转

HImage CAlgorithmModule::HKAImageToHImage(HKA_IMAGE inputimage)
{
	HImage himage;
	if (HKA_IMG_MONO_08 == inputimage.format)
	{
		himage.GenImage1("byte", inputimage.width, inputimage.height, inputimage.data[0]);
	}
	if (HKA_IMG_RGB_RGB24_C3 == inputimage.format)
	{
		int width = inputimage.width;
		int height = inputimage.height;
		long size = width * height * 3;
		byte* imageRedBuf = new byte[(long)width * height];
		byte* imageGreenBuf = new byte[(long)width * height];
		byte* imageBlueBuf = new byte[(long)width * height];
		byte* imageBuffer = new byte[size];
		memcpy(imageBuffer, inputimage.data[0], size);
		int index = 0;
		for (int row = 0; row < height; row++)
		{
			for (int col = 0; col < width; col++, index += 3)
			{
				imageRedBuf[row * width + col] = imageBuffer[index];
				imageGreenBuf[row * width + col] = imageBuffer[index + 1];
				imageBlueBuf[row * width + col] = imageBuffer[index + 2];
			}
		}
		delete[] imageBuffer;
		himage.GenImage3("byte", width, height, imageRedBuf, imageGreenBuf, imageBlueBuf);
	}
	return himage;
}


HKA_IMAGE CAlgorithmModule::HImageToHKAIMAGE(HImage himage)
{
	HKA_IMAGE inputimage;
	HString type;
	Hlong width, height;
	if (himage.CountChannels() == 1)
	{
		inputimage = { HKA_IMG_MONO_08, 0 };
		void* imagePtr = himage.GetImagePointer1(&type, &width, &height);
		inputimage.width = width;
		inputimage.height = height;
		inputimage.format = HKA_IMG_MONO_08;
		inputimage.step[0] = width;
		inputimage.data[0] = (char*)malloc(inputimage.width * inputimage.height);
		if (inputimage.data[0] != NULL)
		{
			memset(inputimage.data[0], 0, inputimage.width * inputimage.height);
			memcpy_s(inputimage.data[0], inputimage.width * inputimage.height, imagePtr, inputimage.width * inputimage.height);
		}
	}
	else if (himage.CountChannels() == 3)
	{
		inputimage = { HKA_IMG_RGB_RGB24_C3, 0 };
		void* imageRedPtr;
		void* imageGreenPtr;
		void* imageBluePtr;
		himage.GetImagePointer3(&imageRedPtr, &imageGreenPtr, &imageBluePtr, &type, &width, &height);		
		long size = width * height * 3;
		byte* imageRedBuf = new byte[width * height];
		byte* imageGreenBuf = new byte[width * height];
		byte* imageBlueBuf = new byte[width * height];
		memcpy_s(imageRedBuf, imageRedPtr, width * height);
		memcpy_s(imageGreenBuf, imageGreenPtr, width * height);
		memcpy_s(imageBlueBuf, imageBluePtr, width * height);
		byte* imageBuffer = new byte[size];
		int index = 0;
		for (int row = 0; row < height; row++)
		{
			for (int col = 0; col < width; col++, index += 3)
			{
				imageBuffer[index] = imageRedBuf[row * width + col];
				imageBuffer[index + 1] = imageGreenBuf[row * width + col];
				imageBuffer[index + 2] = imageBlueBuf[row * width + col];
			}
		}
		delete[] imageRedBuf;
		delete[] imageGreenBuf;
		delete[] imageBlueBuf;
		inputimage.width = width;
		inputimage.height = height;
		inputimage.format = HKA_IMG_RGB_RGB24_C3;
		inputimage.step[0] = width * 3;
		inputimage.data[0] = (char*)malloc(inputimage.width * inputimage.height * 3);
		if (inputimage.data[0] != NULL)
		{
			memset(inputimage.data[0], 0, inputimage.width * inputimage.height * 3);
			memcpy_s(inputimage.data[0], inputimage.width * inputimage.height * 3, imageBuffer, inputimage.width * inputimage.height * 3);
		}
		delete[] imageBuffer;      
	}
	return inputimage;
}

3 HKA_IMAGE与算子图像(CmvdImage)互转

IMvdImage* CAlgorithmModule::HKAImageToIMvdImage(HKA_IMAGE inputimage)
{
    IMvdImage* iMvdImage = NULL;
    CreateImageInstance(&iMvdImage);
    MVD_IMAGE_DATA_INFO stImageData;

    if (inputimage.format == HKA_IMG_MONO_08)
    {
        uint dataLen = (uint)(inputimage.width * inputimage.height);
        stImageData.stDataChannel[0].nRowStep = inputimage.width;
        stImageData.stDataChannel[0].nLen = dataLen;
        stImageData.stDataChannel[0].nSize = dataLen;
        stImageData.stDataChannel[0].pData = (unsigned char*)malloc(inputimage.width * inputimage.height);
        memset(stImageData.stDataChannel[0].pData, 0, inputimage.width * inputimage.height);
        stImageData.stDataChannel[0].pData = (unsigned char*)inputimage.data[0];
        iMvdImage->InitImage(inputimage.width, inputimage.height, MVD_PIXEL_MONO_08, stImageData);
    }
    else if (inputimage.format == HKA_IMG_RGB_RGB24_C3)
    {
        uint dataLen = (uint)(inputimage.width * inputimage.height * 3);
        stImageData.stDataChannel[0].nRowStep = inputimage.width * 3;
        stImageData.stDataChannel[0].nLen = dataLen;
        stImageData.stDataChannel[0].nSize = dataLen;
        stImageData.stDataChannel[0].pData = (unsigned char*)malloc(inputimage.width * inputimage.height * 3);
        memset(stImageData.stDataChannel[0].pData, 0, inputimage.width * inputimage.height);
        stImageData.stDataChannel[0].pData = (unsigned char*)inputimage.data[0];
        iMvdImage->InitImage(inputimage.width, inputimage.height, MVD_PIXEL_RGB_RGB24_C3, stImageData);

    }
    return iMvdImage;
}


HKA_IMAGE CAlgorithmModule::IMvdImageToHKA_IMAGE(IMvdImage* iMvdImage)
{
    HKA_IMAGE inputimage;
    if (iMvdImage->GetPixelFormat() == MVD_PIXEL_MONO_08)
    {
        inputimage = { HKA_IMG_MONO_08, 0 };
        inputimage.width = iMvdImage->GetWidth();
        inputimage.height = iMvdImage->GetHeight();
        inputimage.format = HKA_IMG_MONO_08;
        inputimage.step[0] = iMvdImage->GetWidth();
        inputimage.data[0] = (char*)malloc(inputimage.width * inputimage.height);
        if (inputimage.data[0] != NULL)
        {
            memset(inputimage.data[0], 0, inputimage.width * inputimage.height);
            memcpy_s(inputimage.data[0], inputimage.width * inputimage.height, iMvdImage->GetImageData()->stDataChannel[0].pData, inputimage.width * inputimage.height);
        }
    }
    else if (iMvdImage->GetPixelFormat() == MVD_PIXEL_RGB_RGB24_C3)
    {
        inputimage = { HKA_IMG_RGB_RGB24_C3, 0 };
        inputimage.width = iMvdImage->GetWidth();
        inputimage.height = iMvdImage->GetHeight();
        inputimage.format = HKA_IMG_RGB_RGB24_C3;
        inputimage.step[0] = iMvdImage->GetWidth() * 3;
        inputimage.data[0] = (char*)malloc(inputimage.width * inputimage.height * 3);
        if (inputimage.data[0] != NULL)
        {
            memset(inputimage.data[0], 0, inputimage.width * inputimage.height * 3);
            memcpy_s(inputimage.data[0], inputimage.width * inputimage.height * 3, iMvdImage->GetImageData()->stDataChannel[0].pData, inputimage.width * inputimage.height * 3);
        }
    }
    return inputimage;
}

问题根因
不熟悉算法模块图像转其它类型

猜你喜欢

转载自blog.csdn.net/MVExpert/article/details/130413657