c# 读取二进制dat图像数据 ,使用Emgu显示图像(openCV)

1.项目右键-->Manage Nuget Package中查找Emgu

2.先读取二进制文件至buffer缓冲区,将buffer指针传入mat函数,转换出image,然后显示。

        public Mat(int[] sizes, DepthType type, IntPtr data, IntPtr[] steps = null);
        //
        // Summary:
        //     Create a Mat header from existing data
        //
        // Parameters:
        //   size:
        //     Size of the Mat
        //
        //   type:
        //     Mat element type
        //
        //   channels:
        //     Number of channels
        //
        //   data:
        //     Pointer to the user data. Matrix constructors that take data and step parameters
        //     do not allocate matrix data. Instead, they just initialize the matrix header
        //     that points to the specified data, which means that no data is copied. This operation
        //     is very efficient and can be used to process external data using OpenCV functions.
        //     The external data is not automatically deallocated, so you should take care of
        //     it.
        //
        //   step:
        //     Number of bytes each matrix row occupies. The value should include the padding
        //     bytes at the end of each row, if any.

参考代码如下:

using System;
using System.Drawing;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.Util;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace OpenCV
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {            
            string fPath = @"C:\Users\Antony WU\Desktop\ADBTest20190604\vpu\raw.dat";
            string savePath = @"C:\Users\Antony WU\Desktop\ADBTest20190604\vpu\png.png";
            FileInfo finfo = new FileInfo(fPath);   //实例化FileInfo
            FileStream fs = finfo.OpenRead();

            const int vpu_image_width = 1280;
            const int vpu_image_height = 800;
            Size size = new Size(vpu_image_width, vpu_image_height);
            int bufLength = vpu_image_width* vpu_image_height;//1280*800
            byte[] buffer = new byte[bufLength];   //定义缓冲器
            int readSize = fs.Read(buffer, 0, bufLength);   //从FileStream中读取数据到缓冲区  
            if(readSize>0)
            {
                GCHandle hObject = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                IntPtr pObject = hObject.AddrOfPinnedObject();
                int[] sizes = new int[] { vpu_image_height, vpu_image_width };
                Mat image = new Mat(sizes, DepthType.Cv8U, pObject);
                pictureBox1.Image = image.Bitmap;
                if (hObject.IsAllocated)
                    hObject.Free();
                image.Save(savePath);

                CvInvoke.Imshow("ShowImg", image);
                //CvInvoke.WaitKey(0);
                //Bitmap bmp = ToGrayBitmap(buffer, vpu_image_width, vpu_image_height);
                //pictureBox1.Image = bmp;///方法二也OK
            }
        }
        public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height)
        {
            //// 申请目标位图的变量,并将其内存区域锁定
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);

            //// 获取图像参数
            int stride = bmpData.Stride;  // 扫描线的宽度
            int offset = stride - width;  // 显示宽度与扫描线宽度的间隙
            IntPtr iptr = bmpData.Scan0;  // 获取bmpData的内存起始位置
            int scanBytes = stride * height;  // 用stride宽度,表示这是内存区域的大小

            //// 下面把原始的显示大小字节数组转换为内存中实际存放的字节数组
            int posScan = 0, posReal = 0;  // 分别设置两个位置指针,指向源数组和目标数组
            byte[] pixelValues = new byte[scanBytes];  //为目标数组分配内存

            for (int x = 0; x < height; x++)
            {
                //// 下面的循环节是模拟行扫描
                for (int y = 0; y < width; y++)
                {
                    pixelValues[posScan++] = rawValues[posReal++];
                }
                posScan += offset;  //行扫描结束,要将目标位置指针移过那段“间隙”
            }

            //// 用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中
            System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);
            bmp.UnlockBits(bmpData);  // 解锁内存区域

            //// 下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度
            ColorPalette tempPalette;
            using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
            {
                tempPalette = tempBmp.Palette;
            }
            for (int i = 0; i < 256; i++)
            {
                Color ColorTemp = Color.FromArgb(i, i, i);
                tempPalette.Entries[i] = ColorTemp;
            }

            bmp.Palette = tempPalette;
            //// 算法到此结束,返回结果
            return bmp;
        }
    }
}

 

你可能感兴趣的:(c#,Vs2017)