c#调用c++(Opencv)dll的实例

51 篇文章 3 订阅
36 篇文章 29 订阅

*****************************************c++代码

MYDLL int GetCenterPos(uchar* imageData,int step, int widthValue, int heightValue, int BinaryThreshold, int LineBlankThreshold, int* centerX, int* centerY)
{
    
    //Mat src(widthValue, heightValue, CV_8UC3);
    //cvtColor(src, src, CV_RGB2GRAY);
    //memcpy(imageData, src.data, sizeof(uchar)*src.rows*src.cols * 3);
    Mat src = cv::Mat(heightValue, widthValue, CV_8UC4, imageData,step);//很重要的参数:CV_8UC4
    /*return src.cols;*/
    /*return src.rows;*/
    /*imshow("图1", src);*/
    /*return 99;*/
    
    int ImageWidth = src.cols;
    int ImageHeight = src.rows;
    /*Mat src ImageWidth= imread(path);*/
    // 结果图
    Mat dst;
    //灰度图转换
    cvtColor(src, dst, COLOR_RGB2GRAY);
    // 高斯模糊,主要用于降噪

    GaussianBlur(dst, dst, Size(3, 3), 0);
    
    // 二值化图,主要将灰色部分转成白色,使内容为黑色
    threshold(dst, dst, BinaryThreshold, 255, THRESH_BINARY_INV);

    // 中值滤波,同样用于降噪
    medianBlur(dst, dst, 3);
    //blur(dst, dst, Size(3, 3));//平滑处理
    
    //***********获取中心算法
    /*imshow("图2", dst);*/
    //********************************************横向遍历
    //map<int, int> horizonMap;//提取词典
    vector<int> vecMyHouse(0);
    vector<int> HorizonMyHouse(0);
    int height = dst.rows;
    int width = dst.cols;
    
    for (int i = 0; i < height; i++) {
        if (i % LineBlankThreshold == 0)
        {

            int num = 0;
            vecMyHouse.clear();
            
            for (int j = 0; j < width; j++) {
                int index = i * width + j;
                //像素值        
                int data = (int)dst.data[index];
                
                if (data == 0)
                {        
                    /*mp.X = j;
                    mp.Y = i;*/
                    
                    vecMyHouse.push_back(j);
                    
                }

            }
            
            //******
            int tempX = 0;
            int tempY = 0;
            int count = vecMyHouse.size();
            if (count > 50)
            {
                int a = 0;
            }
            if (vecMyHouse.size() <3)continue;
            if (vecMyHouse.size() > 20)continue;        
            //sort(vecMyHouse.begin(), vecMyHouse.end());//大小排序
            //最大值:            
            int max = *max_element(vecMyHouse.begin(), vecMyHouse.end());//过滤
            int min = *min_element(vecMyHouse.begin(), vecMyHouse.end());//过滤
            int tempCount = 0;
            //利用keySet方法将map中键放入到Set中,可以使用  增强for
            for (int k = 0; k < vecMyHouse.size(); k++) {
                if (vecMyHouse[k] != max&&vecMyHouse[k] != min)
                {
                    tempX += vecMyHouse[k];
                    tempCount++;
                }

            }
            int value = (int)(tempX*1.0 / tempCount);
            
            HorizonMyHouse.push_back(value);
            num++;
        }
    }
    int tempX = 0;
    //最大值:
    int max = *max_element(HorizonMyHouse.begin(), HorizonMyHouse.end());//过滤
    //最小值:
    int min = max;//*min_element(HorizonMyHouse.begin(), HorizonMyHouse.end());//过滤
    sort(HorizonMyHouse.begin(), HorizonMyHouse.end());//大小排序
    int count = HorizonMyHouse.size();
    for (int z = 0; z < HorizonMyHouse.size(); z++)
    {
        if (min>HorizonMyHouse[z] && HorizonMyHouse[z] != 0)
        {
            min = HorizonMyHouse[z];
        }
        tempX += HorizonMyHouse[z];
    }
    tempX = tempX - (max + min);
    if (HorizonMyHouse.size() > 2)
    {

        *centerX = (tempX *1.0 / (HorizonMyHouse.size() - 2));
    }
    else
    {
        *centerX = (HorizonMyHouse[0] + HorizonMyHouse[1]) / 2;
    }
    *centerX += 1;

    
#if 1
    //********************************************纵向遍历
    //map<int, int> horizonMap;//提取词典
    vector<int> vecMyHouse2(0);
    vector<int> verticalMyHouse(0);
    height = dst.rows;
    width = dst.cols;
    for (int i = 0; i < width; i++) {
        if (i % LineBlankThreshold == 0)
        {
            int num = 0;
            vecMyHouse2.clear();

            for (int j = 0; j < height; j++) {
                int index = j * width + i;
                //像素值        
                int data = (int)dst.data[index];
                if (data == 0)
                {
                /*    mp.X = i;
                    mp.Y = j;*/

                    vecMyHouse2.push_back(j);

                }

            }
            //******
            int tempX = 0;
            int tempY = 0;
            int count = vecMyHouse.size();
            if (vecMyHouse2.size() <3)continue;
            if (vecMyHouse2.size() > 20)continue;
            sort(vecMyHouse2.begin(), vecMyHouse2.end());//大小排序
            //最大值:
            int max = *max_element(vecMyHouse2.begin(), vecMyHouse2.end());//过滤
            int min = *min_element(vecMyHouse2.begin(), vecMyHouse2.end());//过滤
            int tempCount = 0;
            //利用keySet方法将map中键放入到Set中,可以使用  增强for
            for (int k = 0; k < vecMyHouse2.size(); k++) {
                if (vecMyHouse2[k] != max&&vecMyHouse2[k] != min)
                {
                    tempX += vecMyHouse2[k];
                    tempCount++;
                }


            }
            int value = (int)(tempX / tempCount);
            verticalMyHouse.push_back(value);
            num++;
            
        }
    }
    
    int tempY = 0;
    //最大值:
    max = *max_element(verticalMyHouse.begin(), verticalMyHouse.end());//过滤
    //最小值:
    min = max; //*min_element(verticalMyHouse.begin(), verticalMyHouse.end());//过滤
    for (int z = 0; z < verticalMyHouse.size(); z++)
    {
        if (min>verticalMyHouse[z] && verticalMyHouse[z] != 0)
        {
            min = verticalMyHouse[z];
        }
        tempY += verticalMyHouse[z];
    }
    
    tempY = tempY - (max + min);
    if (verticalMyHouse.size()>2)
    {
        *centerY = tempY / (verticalMyHouse.size() - 2);
    }
    else
    {
        *centerY = (verticalMyHouse[0] + verticalMyHouse[1]) / 2;
    }

    *centerY += 1;
#endif
        return 0;
}

**********************************C#代码

 public class ImageDll
    {
       [DllImport(@"G:\whh\2020\projectTest\c++\ImageAnalysis\ImageAnalysisTest2020.1.3\ImageAnalysisTest\x64\Debug\CrossDiscern.dll", EntryPoint = "GetCenterPos", CallingConvention = CallingConvention.Cdecl)]
       public static extern int GetCenterPos(IntPtr imageData,int step, int widthValue, int heightValue, int BinaryThreshold, int LineBlankThreshold, ref int centerX, ref int centerY);

       [DllImport(@"CrossDiscern.dll", EntryPoint = "Sum", CallingConvention = CallingConvention.Cdecl)]
       public static extern int Sum(int a, int b);

       //**********图片数据转换
       public static int GetPositionResult_XY(Bitmap bitmap,int BinaryThreshold, int LineBlankThreshold, ref int centerX, ref int centerY)
       {
#if false
           BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
           IntPtr pSt = bmpdata.Scan0;
           int bytes = bitmap.Width * bitmap.Height * 3;
           byte[] rgbValues = new byte[bytes];
           Marshal.Copy(pSt, rgbValues, 0, bytes);
          
           int res = GetCenterPos(rgbValues, bmpdata.Stride, bitmap.Width, bitmap.Height, BinaryThreshold, LineBlankThreshold, ref centerX, ref  centerY);
           bitmap.UnlockBits(bmpdata);
           return res;
#endif
#if true
           BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
           IntPtr pSt = bmpdata.Scan0;
           int bytes = bitmap.Width * bitmap.Height * 3;
           byte[] rgbValues = new byte[bytes];
           Marshal.Copy(pSt, rgbValues, 0, bytes);

           int res = GetCenterPos(pSt, bmpdata.Stride, bitmap.Width, bitmap.Height, BinaryThreshold, LineBlankThreshold, ref centerX, ref  centerY);
           bitmap.UnlockBits(bmpdata);
           return res;
#endif
       }

    }

c#调用

 private void button_GetCenterPos_Click(object sender, EventArgs e)
        {
            Bitmap map = new Bitmap(sourceImage);
            int x=0;
            int y=0;
           if( ImageDll.GetPositionResult_XY(map, 80, 20, ref x, ref y)==0)
           {
             
               //MessageBox.Show("识别成功!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
               string content = "";//"图像大小:" + "\r\n";
               content += "起点:X=0 Y=0"+"\r\n";
               content +=( "终点:X=" + map.Width.ToString()+" Y="+map.Height.ToString()+"\r\n");
               content += "中线点:X=" + x.ToString() + " Y=" + y.ToString() + "\r\n";
               label4.Text = content;
               //*********绘制中心点
               Graphics graphics = panel3.CreateGraphics();
               Font font = new Font("宋体",16,FontStyle.Bold/*|FontStyle.Italic|FontStyle.Underline*/,GraphicsUnit.Point);//其中宋体是字体,24是字号,FontStyle的几个是字的样式,最后的GraphicsUnit是字的度量单位(可以看一下上边的表)
               graphics.DrawString("识别成功!\r\n" + content, font, Brushes.Blue, new Point(panel3.Width / 2 - 72, 25));//绘制字体,font是上边定义的字体,Brushes.Brown是颜色,Point是字从哪个位置开始绘制
          
               Brush b = new SolidBrush(Color.Red);//声明的画刷

               int margin = 20;
               int tempx = Convert.ToInt32(x * 1.0 / map.Width * (panel3.Width - 2 * margin) + margin);
               int tempy = Convert.ToInt32(y * 1.0 / map.Height * (panel3.Height - 2 * margin) + margin);
               graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;//平滑绘制
               graphics.FillEllipse(b, new Rectangle(tempx-5,tempy-5, 10,10));             
               graphics.Dispose();
           }
           else
           {
               MessageBox.Show("识别失败!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
           }
        }

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在C#调用C++编写的OpenCV dll,可以使用Platform Invoke(P/Invoke)技术。下面是一个简单的示例,演示如何在C#调用C++编写的OpenCV dll: 1. 创建一个新的C#控制台应用程序。 2. 在项目文件夹中创建一个名为“opencv”的子文件夹。 3. 将OpenCV dll文件复制到该子文件夹中。 4. 在Visual Studio中打开项目,并添加以下代码: ```C# using System; using System.Runtime.InteropServices; class Program { [DllImport("opencv\\opencv_core320.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr cvCreateImage( [MarshalAs(UnmanagedType.Struct)] CvSize size, int depth, int channels); static void Main(string[] args) { // 创建一个256x256的8位单通道图像 var size = new CvSize(256, 256); var image = cvCreateImage(size, 8, 1); // 在控制台中输出图像信息 Console.WriteLine("Image created: {0}x{1}, depth={2}, channels={3}", size.Width, size.Height, 8, 1); Console.ReadKey(); } } [StructLayout(LayoutKind.Sequential)] public struct CvSize { public int Width; public int Height; public CvSize(int width, int height) { Width = width; Height = height; } } ``` 上面的代码创建了一个256x256的8位单通道图像,并在控制台中输出了图像信息。 在上面的代码中,我们使用DllImport属性来指定要导入的OpenCV dll的名称和调用约定。在本例中,我们使用Cdecl调用约定。 我们还定义了一个结构体CvSize,用于传递图像大小参数。在C++中,CvSize结构体定义在opencv_core.hpp头文件中。我们在C#中重新定义了这个结构体,以便我们可以在C#中使用它来传递参数。 需要注意的是,由于C++C#使用不同的内存管理机制,因此您需要确保在C#中正确处理从C++返回的指针。在本例中,我们使用IntPtr类型来表示从C++返回的指针,并使用Marshal类中的相关方法来管理它们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值