上一篇 将C++ IplImage 图像用C#读取 的方法只适用于自己的电脑,而如果是将工程放到别的计算机,debug版本可以工作
release 版本就不能正常工作了,原因在于指针。具体的可以自己学习了解。(目前发现,部分电脑能用,部分不能用,有知道的可以告诉我下是什么问题,谢谢了
-----已经解决
因为少了一个tbb.dll,现在别人电脑可以使用了。但是单独的dependency看不出来,后来用的是procexp,对比别人的电脑和我的电脑dll的差别看出来的,上一篇的方法应该没有问题)
这次我换一种方法,供大家参考。
此方法经过其他机器的测试
CvMat 可以用类似的方法转换。
dll 代码
#include "stdafx.h" #define DLL_API extern "C" _declspec(dllexport) #include <opencv2\opencv.hpp> DLL_API IplImage* _stdcall test(char* fileName) { IplImage* src = cvLoadImage(fileName); return src; }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Emgu.CV; using Emgu.CV.Structure; using Emgu.Util; using System.Runtime.InteropServices; namespace 1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } [DllImport("1.dll")] // unsafe public static extern IntPtr test(string fileName); //unsafe private void button1_Click(object sender, EventArgs e) { OpenFileDialog open = new OpenFileDialog(); if (open.ShowDialog() == DialogResult.OK) { IntPtr pp = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MIplImage))); pp = test(open.FileName); MIplImage d = (MIplImage)Marshal.PtrToStructure((IntPtr)(pp.ToInt32()), typeof(MIplImage)); IntPtr aa = new IntPtr(); aa = d.imageData; int width = d.width; int step = d.widthStep; int height = d.height; using (Image<Bgr, byte> src = new Image<Bgr, byte>(width, height, step, aa)) { pictureBox1.Image = src.ToBitmap(); } } } } }
下面是我按照C++的格式对应写的结构体 [StructLayout(LayoutKind.Sequential)] public struct MIplImage { // // 摘要: // sizeof(IplImage) public int nSize; // // 摘要: // version (=0) public int ID; // // 摘要: // Most of OpenCV functions support 1,2,3 or 4 channels public int nChannels; // // 摘要: // ignored by OpenCV public int alphaChannel; // // 摘要: // 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 public IPL_DEPTH depth; // // 摘要: // ignored by OpenCV public byte colorModel0; // // 摘要: // ignored by OpenCV public byte colorModel1; // // 摘要: // ignored by OpenCV public byte colorModel2; // // 摘要: // ignored by OpenCV public byte colorModel3; // // 摘要: // ignored by OpenCV public byte channelSeq0; // // 摘要: // ignored by OpenCV public byte channelSeq1; // // 摘要: // ignored by OpenCV public byte channelSeq2; // // 摘要: // ignored by OpenCV public byte channelSeq3; // // 摘要: // 0 - interleaved color channels, 1 - separate color channels. cvCreateImage // can only create interleaved images public int dataOrder; // // 摘要: // 0 - top-left origin, 1 - bottom-left origin (Windows bitmaps style) public int origin; // 摘要: // Alignment of image rows (4 or 8). OpenCV ignores it and uses widthStep instead public int align; // // 摘要: // image width in pixels public int width; // // 摘要: // image height in pixels public int height; // // 摘要: // image ROI. when it is not NULL, this specifies image region to process public IntPtr roi; // // 摘要: // must be NULL in OpenCV public IntPtr maskROI; // // 摘要: // ditto public IntPtr imageId; // // 摘要: // ditto public IntPtr tileInfo; // // 摘要: // image data size in bytes (=image->height*image->widthStep in case of interleaved // data) public int imageSize; // // 摘要: // pointer to aligned image data public IntPtr imageData; // // 摘要: // size of aligned image row in bytes public int widthStep; // // 摘要: // border completion mode, ignored by OpenCV public int BorderMode0; // // 摘要: // border completion mode, ignored by OpenCV public int BorderMode1; // // 摘要: // border completion mode, ignored by OpenCV public int BorderMode2; // // 摘要: // border completion mode, ignored by OpenCV public int BorderMode3; // // 摘要: // border const, ignored by OpenCV public int BorderConst0; // // 摘要: // border const, ignored by OpenCV public int BorderConst1; // // 摘要: // border const, ignored by OpenCV public int BorderConst2; // // 摘要: // border const, ignored by OpenCV public int BorderConst3; // // 摘要: // pointer to a very origin of image data (not necessarily aligned) - it is // needed for correct image deallocation public IntPtr imageDataOrigin; }
对于不用EMGUCV的人 可以自己复制一个MIplImage 的结构体
这里还需要DEPTH这个类
public enum IPL_DEPTH { // 摘要: // 1bit unsigned IPL_DEPTH_1U = 1, // // 摘要: // 8bit unsigned (Byte) IPL_DEPTH_8U = 8, // // 摘要: // 16bit unsigned IPL_DEPTH_16U = 16, // // 摘要: // 32bit float (Single) IPL_DEPTH_32F = 32, // // 摘要: // double IPL_DEPTH_64F = 64, // // 摘要: // indicates if the value is signed IPL_DEPTH_SIGN = 0x80000000, // // 摘要: // 8bit signed IPL_DEPTH_8S = IPL_DEPTH_SIGN| 8, // // 摘要: // 16bit signed IPL_DEPTH_16S = IPL_DEPTH_SIGN|16, // // 摘要: // 32bit signed IPL_DEPTH_32S = IPL_DEPTH_SIGN|32, }
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; } } }
aa = d.imageData; int height = d.height; int step = d.widthStep; Bitmap img = new Bitmap(width, height, step, System.Drawing.Imaging.PixelFormat.Format8bppIndexed, aa); img.Palette = CvToolbox.GrayscalePalette; bigImage.Image = img;