上一篇 将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;
1、将Mat转换为IplImage
//! converts header to IplImage; no data is copied
operator IplImage() const;
举例:Mat img;
IplImage *src;
src=&IplImage(img);
2、将IplImage转换为Mat
//! converts old-style IplImage to the new matrix; the data is not copied by default
Mat(const IplImage* img, bool copyData=false);