IplImage转换为Bitmap

如何将OpenCV中的Iplimage转化为C#中的Bitmap

GitHub代码地址:https://github.com/peiyixi/IplImageToBitmap
完整代码可以直接去GitHub上下载,上面还有一个小的demo程序
最近项目用到了OpenCV与C#的交互问题,通过查阅信息和看源码总结了出一种将Iplimage转化为Bitmap的方法
废话不多说直接上代码吧

代码:

1、首先建立一个MIplImage的struct:
(复制的Emgu中的源码,直接复制粘贴就好)

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace IplImageToBitmap.cv

{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct MIplImage
    {
        /// <summary>
        /// sizeof(IplImage) 
        /// </summary>
        public int NSize;
        /// <summary>
        /// version (=0)
        /// </summary>
        public int ID;
        /// <summary>
        /// Most of OpenCV functions support 1,2,3 or 4 channels 
        /// </summary>
        public int NChannels;
        /// <summary>
        /// ignored by OpenCV 
        /// </summary>
        public int AlphaChannel;
        /// <summary>
        /// pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U, IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported 
        /// </summary>
        public IplDepth Depth;
/// <summary>
        /// ignored by OpenCV 
        /// </summary>
        public byte ColorModel0;
        /// <summary>
        /// ignored by OpenCV 
        /// </summary>
        public byte ColorModel1;
        /// <summary>
        /// ignored by OpenCV 
        /// </summary>
        public byte ColorModel2;
        /// <summary>
        /// ignored by OpenCV 
        /// </summary>
        public byte ColorModel3;

    /// <summary>
    /// ignored by OpenCV 
    /// </summary>
    public byte ChannelSeq0;
    /// <summary>
    /// ignored by OpenCV 
    /// </summary>
    public byte ChannelSeq1;
    /// <summary>
    /// ignored by OpenCV 
    /// </summary>
    public byte ChannelSeq2;
    /// <summary>
    /// ignored by OpenCV 
    /// </summary>
    public byte ChannelSeq3;

    /// <summary>
    /// 0 - interleaved color channels, 1 - separate color channels.
    /// cvCreateImage can only create interleaved images 
    /// </summary>
    public int DataOrder;
    /// <summary>
    /// 0 - top-left origin,
    /// 1 - bottom-left origin (Windows bitmaps style)
    /// </summary>
    public int Origin;
    /// <summary>
    /// Alignment of image rows (4 or 8).
    /// OpenCV ignores it and uses widthStep instead 
    /// </summary>
    public int Align;
    /// <summary>
    /// image width in pixels 
    /// </summary>
    public int Width;
    /// <summary>
    /// image height in pixels 
    /// </summary>
    public int Height;
    /// <summary>
    /// image ROI. when it is not NULL, this specifies image region to process 
    /// </summary>
    public IntPtr Roi;
    /// <summary>
    /// must be NULL in OpenCV 
    /// </summary>
    public IntPtr MaskROI;
    /// <summary>
    /// ditto
    /// </summary>
    public IntPtr ImageId;
    /// <summary>
    /// ditto 
    /// </summary>
    public IntPtr TileInfo;
    /// <summary>
    /// image data size in bytes
    /// (=image->height*image->widthStep in case of interleaved data)
    /// </summary>
    public int ImageSize;
    /// <summary>
    /// pointer to aligned image data 
    /// </summary>
    public IntPtr ImageData;
    /// <summary>
    /// size of aligned image row in bytes 
    /// </summary>
    public int WidthStep;

    /// <summary>
    /// border completion mode, ignored by OpenCV 
    /// </summary>
    public int BorderMode0;
    /// <summary>
    /// border completion mode, ignored by OpenCV 
    /// </summary>
    public int BorderMode1;
    /// <summary>
    /// border completion mode, ignored by OpenCV 
    /// </summary>
    public int BorderMode2;
    /// <summary>
    /// border completion mode, ignored by OpenCV 
    /// </summary>
    public int BorderMode3;

    /// <summary>
    /// border const, ignored by OpenCV 
    /// </summary>
    public int BorderConst0;
    /// <summary>
    /// border const, ignored by OpenCV 
    /// </summary>
    public int BorderConst1;
    /// <summary>
    /// border const, ignored by OpenCV 
    /// </summary>
    public int BorderConst2;
    /// <summary>
    /// border const, ignored by OpenCV 
    /// </summary>
    public int BorderConst3;

    /// <summary>
    ///  pointer to a very origin of image data (not necessarily aligned) - it is needed for correct image deallocation 
    /// </summary>
    public IntPtr ImageDataOrigin;
}

}
struct MIplImage中还需要用到enum IplDepth也直接复制吧:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace IplImageToBitmap.cv
{
   public enum IplDepth : uint
    {
        /// <summary>
        /// indicates if the value is signed
        /// </summary>
        IplDepthSign = 0x80000000,
        /// <summary>
        /// 1bit unsigned
        /// </summary>
        IplDepth_1U = 1,
        /// <summary>
        /// 8bit unsigned (Byte)
        /// </summary>
        IplDepth_8U = 8,
        /// <summary>
        /// 16bit unsigned
        /// </summary>
        IplDepth16U = 16,
        /// <summary>
        /// 32bit float (Single)
        /// </summary>
        IplDepth32F = 32,
        /// <summary>
        /// 8bit signed
        /// </summary>
        IplDepth_8S = (IplDepthSign | 8),
        /// <summary>
        /// 16bit signed
        /// </summary>
        IplDepth16S = (IplDepthSign | 16),
        /// <summary>
        /// 32bit signed 
        /// </summary>
        IplDepth32S = (IplDepthSign | 32),
        /// <summary>
        /// double
        /// </summary>
        IplDepth64F = 64
    }

}

2、然后就可以调用IpilImage了:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Runtime.InteropServices;
using IplImageToBitmap.cv;
using IplImageToBitmap;
using System.Drawing.Imaging;
namespace IplImageToBitmap
{
    public static class Ctransform
    {
        /// <summary>
        /// 将IplImage指针转换成位图对象;
        /// </summary>
        /// <param name="ptr">IplImage指针</param>
        /// <returns>返回位图对象</returns>

        public static Bitmap IplImageToBitmap(IntPtr ptr)
        {
            IntPtr pp = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MIplImage)));
            pp = ptr;
            PixelFormat pixelFormat;   //像素格式

            MIplImage mptr = (MIplImage)Marshal.PtrToStructure((IntPtr)(pp.ToInt32()), typeof(MIplImage));
            IntPtr aa = new IntPtr();
            aa = mptr.ImageData;
            int width = mptr.Width;
            int height = mptr.Height;
            int step = mptr.WidthStep;
            string unsupportedDepth = "不支持的像素位深度IPL_DEPTH";
            string unsupportedChannels = "不支持的通道数(仅支持1,2,4通道)";
            switch (mptr.NChannels)                     //根据深度和通道数对应C#中的像素的颜色数据格式                           
            {
                case 1:    //Grayscale image;         
                    switch (mptr.Depth)
                    {
                        case IplDepth.IplDepth_8U:
                            pixelFormat = PixelFormat.Format8bppIndexed;
                            break;
                        case IplDepth.IplDepth16U:
                            pixelFormat = PixelFormat.Format16bppGrayScale;
                            break;
                        default:
                            throw new NotImplementedException(unsupportedDepth);
                    }
                    break;
                case 3: //BGR image           
                    switch (mptr.Depth)
                    {
                        case IplDepth.IplDepth_8U:
                            pixelFormat = PixelFormat.Format24bppRgb;
                            break;
                        case IplDepth.IplDepth16U:
                            pixelFormat = PixelFormat.Format48bppRgb;

                            break;
                        default:
                            throw new NotImplementedException(unsupportedDepth);

                    }
                    break;

                case 4:
                    switch (mptr.Depth)
                    {
                        case IplDepth.IplDepth_8U:
                            pixelFormat = PixelFormat.Format32bppArgb;
                            break;
                        case IplDepth.IplDepth16U:
                            pixelFormat = PixelFormat.Format64bppArgb;
                            break;
                        default:
                            throw new NotImplementedException(unsupportedDepth);
                    }
                    break;
                default:
                    throw new NotImplementedException(unsupportedChannels);
            }
           Bitmap img = new Bitmap(width, height, step, pixelFormat, aa);
           //对于灰度图像,还要修改调色板
           if (pixelFormat == PixelFormat.Format8bppIndexed)
           {
               img.Palette = CvToolbox.GrayscalePalette;
           }

            return img;
        }
         
    }
}

上面的灰度图像的调色板函数,我建了一个CvToolbox类:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IplImageToBitmap.cv
{
    public static class CvToolbox
    { // #region Color Pallette
        /// <summary>
        /// The ColorPalette of Grayscale for Bitmap Format8bppIndexed
        /// </summary>
        public static readonly ColorPalette GrayscalePalette = GenerateGrayscalePalette();
 
        private static ColorPalette GenerateGrayscalePalette()
        {
            using (Bitmap image = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
            {
                ColorPalette palette = image.Palette;
                for (int i = 0; i < 256; i++)
                {
                    palette.Entries[i] = Color.FromArgb(i, i, i);
                }
                return palette;
            }
        }

    }
}

参考博客:https://blog.csdn.net/yeyang911/article/details/23735145

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值