在C#中使用C++的DLL,并且在DLL中包含有opencv的代码,通过“障眼法”操作

最近,老师在做项目,要我实现上述标题需求。

配置环境:

系统:win7  X64

工具:vs2012

使用工具:OpenCVSharp  

第一步:

  主要工作为:怎么让openCV在C#的环境下进行使用?我们可以使用”障眼法“。
1、刚开始,是打算用emguCV搭建,但是工作过程中,由于emguCV在win7中对应的opencv的最新版本只有2.4.2,而我们想用的工具是vs2012,在配置emguCV之前,要先搭载openCV环境,一般的环境搭建的教程,都是VS2012+2.4.3的版本,所以放弃了使用这一工具。
2、后来经过搜索,打算用OpenCvSharp,这个配置简单,而且现在和openCV更新的一样快,版本已经到2.4.9了
   这是openCVSharp的配置过程如下:

   http://blog.csdn.net/sussii/article/details/8521635

   这是在C#环境中opencv关于C++的一些API的应用:

   https://github.com/shimat/opencvsharp/wiki/%5BCpp%5D-Accessing-Pixel
   这里面既有C的API,又有C++的API的一些例子,在C#环境下

   https://github.com/shimat/opencvsharp/wiki
   这里是openCvSharp的一些教程

   http://www.boyunjian.com/v/softd/OpenCVSharp.html
   这里是openCvSharp对应的openCV的各种版本的下载和Sample 

   https://github.com/shimat/opencvsharp/releases
下载对应的openCvSharp版本,就可以根据配置过程进行配置,配置完成以后,可以在第二个网址中找一些在C#环境中opencv关于C++的一些API
进行测试。
我遇到的问题:报异常
“System.TypeInitializationException”类型的未经处理的异常在 OpenCvSharp_test.exe 中发生 
其他信息: “OpenCvSharp.CPlusPlus.Mat”的类型初始值设定项引发异常。


原因:是因为在openCVsharp中的一个Dll没有拷贝到release或者debug下(至于是哪个,要看你是在那个环境下开发),这个库是OpenCvSharpExtern.dll这个库还不能在reference下引用,报错误:请确保是一个有效的程序集或者COM组件。把他直接拷贝到release下,或者Debug下就行。


第二步:环境配好了,我们下面就用这个环境,用C++建立动态链接库我就不多说了,在这里给一个参考网址,都是我测试过的。这个网址中内容的前三步是用C++建立动态链接库:

http://blog.sina.com.cn/s/blog_6fe1657d0100t72v.html
第四步以后就是我自己的了,下面是我在Dll中写的代码(已经测试成功),我这个DLL的名字是DemoDll.dll

<span style="font-size:14px;">#include "stdafx.h"
#include <opencv2/opencv.hpp>
using namespace cv;

extern "C" __declspec(dllexport) void Show()  
 {  
	 Mat image = imread("1.jpg");
	 namedWindow("image");
	 imshow("image",image);
	 waitKey(0);
     return ;
 }</span>
第三步,在C#中用动态链接库(DLL),代码:

<span style="font-size:14px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;
//using OpenCvSharp;

//namespace OpenCvSharp_test
//{
//    static class Program
//    {
//        /// <summary>
//        /// 应用程序的主入口点。
//        /// </summary>
//        [STAThread]
//        static void Main()
//        {

//            IplImage src = Cv.LoadImage("d:\\lena.jpg", LoadMode.GrayScale);
//            IplImage dst = Cv.CreateImage(new CvSize(src.Width, src.Height), BitDepth.U8, 1);
//            Cv.Canny(src, dst, 50, 200);
//            Cv.NamedWindow("src image");
//            Cv.ShowImage("src image", src);
//            Cv.NamedWindow("dst image");
//            Cv.ShowImage("dst image", dst);
//            Cv.WaitKey(0);
//            Cv.DestroyAllWindows();
//            Cv.ReleaseImage(src);
//            Cv.ReleaseImage(dst);

//            Application.EnableVisualStyles();
//            Application.SetCompatibleTextRenderingDefault(false);
//            Application.Run(new Form1());
//        }
//    }
//}
//以上的注释部分是针对openCV2.0以前的关于C的接口的</span>
//下面的是针对C++接口的</span>
using OpenCvSharp;
using OpenCvSharp.CPlusPlus;


static class Program
{
    /*[DllImport("dll_test.dll")]
    public static extern int test2(Mat image,ref float fudian);

    [DllImport("AddDll.dll")]
    public static extern int Add(ref int x,ref int y);*/

    [DllImport("DemoDll.dll")]
    public static extern void Show();
    static void Main()
    {
        Show(); //这是dll中的函数
        
    }
}
</span>

注意的问题:1、这里在用C++生成DLL的时候,和在C#中使用DLL时候,环境要相同,否则会报异常。我的是X64系统,和vs2012。所以生成DLL的环境也应该是这个,C#的环境也是这个。

2、我这个还遇到的问题是传递参数的问题,若果你传递的是对于 int*, int&, 则都可用 ref int 对应。对于一些字符串,指针的参数什么的,这篇文章有详细说明:

http://jljlpch.iteye.com/blog/520509 

但是上述文章中讲的并不是过于直观,所以这里还是给出一个例子,例子主要介绍的是参数传递的问题,代码中主要传递的参数有int ,char * 结构体,如下:

C++生成的Dll中的代码:

/*
实现功能:将一个图片中,所在行的像素值,按照一定的间隔(列数),将对应点的像素值提取出来。
*/

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include <iostream>
#include <stdio.h>
#include <time.h>
using namespace std;
using namespace cv;

struct Node
{
	int R;
	int G;
	int B;
};

extern "C" _declspec(dllexport)  bool operator_Image(char *path , int rownum,int intervalNum,struct Node *Result,int *Num)
{
	Mat src = imread(path);
	int rows,cols;
	int x = 0,y = 0;
	//cout << src.row(100) << endl;
	rows = src.rows;
	cols = src.cols;
	if (src.empty())
	{
		cout << "图片不存在!" << endl;
	}
	if (rows < intervalNum)
	{
		cout << "你输入的间隔有误!!" << endl;
	}
	//创建动态数组,用来保存像素的值
	//Result = new int[cols/intervalNum*3*sizeof(int)];
	//int savedata[10000] = {0};

	*Num = cols/intervalNum*3;


	int i = 0;
	while(x<cols)
	{
			y = rownum;
			//Result[i++] = src.at<Vec3b>(y,x)[0];
			//Result[i++] = src.at<Vec3b>(y,x)[1];
			//Result[i++] = src.at<Vec3b>(y,x)[2];
			Result[i].G = src.at<Vec3b>(y,x)[0];
			Result[i].B = src.at<Vec3b>(y,x)[1];
			Result[i].R = src.at<Vec3b>(y,x)[2];
			/*if (x%100 == 0)
			{
			printf("%d ",src.at<Vec3b>(y,x)[0]);
			printf("%d ",src.at<Vec3b>(y,x)[1]);
			printf("%d ",src.at<Vec3b>(y,x)[2]);
			}*/
			x = x+intervalNum;	
			i++;
	}
	return true;

}
C#生成的工程调用C++的dll代码如下:

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 System.Runtime.InteropServices;

public struct Node
    {
        int R;
        int G;
        int B;
    };

namespace TestLSPVC
{
     public partial class Form1 : Form
    {

        [DllImport("readcolpixelDll.dll", EntryPoint = "operator_Image", CharSet = CharSet.Ansi)]
        public static extern bool operator_Image(string path , int rownum,int intervalNum, ref  Node Result,ref int Num);


        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string path = "c:\\lena.jpg";
            Node[] x = new  Node[1000];
            int Count=0;
            operator_Image(path,100,100,ref x[0],ref Count);

        }
    }
}


3、本来在这里传递的参数是opencv的函数,如Mat,但是总是出现异常为:

这个错误托管调试助手“NonComVisibleBaseClass”在“D:\13liushuanpeng\OpenCvSharp_test\OpenCvSharp_test\bin\Release\OpenCvSharp_test.vshost.exe”中检测到故障。
其他信息: 执行了 QueryInterface 调用,请求提供 COM 可见的托管类“OpenCvSharp.CPlusPlus.Mat”的类接口。不过,由于该类是从非 COM 可见的类“OpenCvSharp.DisposableCvObject”派生的,QueryInterface 调用将失败。这样做的目的是避免非 COM 可见的基类受 COM 版本规则的约束。

目前还没有解决,希望有知道的联系我。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值