c#调用c++ dll获取图片某种颜色所占百分比

c++ dll

根据之前的c++ dll书写方法

将C++代码编译成一个dll文件

(1)在之前的C++代码上,在解决方案资源管理器中新建一个头文件(.h)
hsv
(2)在新建的头文件中,输入以下内容:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include <opencv2/highgui/highgui_c.h>
#include <string>
#include <unordered_map>
#include <map>
#include <iomanip>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
using namespace cv;
class Triple {
private:
    char* _color;
    float _percentage;
public:
    Triple(char* color, float percentage) {
        _color = color;
        _percentage = percentage;
    }
    virtual ~Triple() {}
    char* Getcolor() { return _color; }
    float Getpercentage() { return _percentage; }
};

extern "C" __declspec(dllexport) void Mat_color_Find(char* qimage);
extern "C" __declspec(dllexport) void hsv_percentage(Mat hsv_image);//因为c#与c++之间,string不能直接转换

这里封装一个类Triple,包含两个变量,构造函数和析构函数,两个方法。
(3)在之前的C++文件中,直接修改代码

#include "hsv_percentage.h"
using namespace std;
using namespace cv;
unordered_map<char*, float> record;
typedef struct {
    char color[32];
    float percentage;
}Hsv;
Triple* triple;
extern "C" __declspec(dllexport) Hsv * Create() {
    //Hsv hsv1[9];
    Hsv* hsv = (Hsv*)malloc(sizeof(Hsv) * 9);
    //triple = new Triple();
    int i = 0;
    for (auto it = record.begin(); it != record.end(); it++) {
        //cout << it->first << " " << it->second << endl;
        triple = new Triple(it->first,it->second);
        strcpy_s(hsv[i].color, triple->Getcolor());
        hsv[i].percentage = triple->Getpercentage();
        i++;
    }
    return hsv;
    
}
/*
区分不同颜色,在图片中所占百分比
*/
void hsv_percentage(Mat hsv_image) {
    int num_black = 0;
    int num_grey = 0;
    int num_white = 0;
    int num_red = 0;
    int num_orange = 0;
    int num_yellow = 0;
    int num_green = 0;
    int num_blue = 0;
    int num_purple = 0;
    //vector<float> record(9,0);
    
    float area = (float)(hsv_image.rows * hsv_image.cols);
    for (int i = 0; i < hsv_image.rows; i++) //行数
    {
        for (int j = 0; j < hsv_image.cols; j++)   //列数
        {
            //在这里操作具体元素
            //{"black", 0, 0, 0, 180, 255, 46}
            if ((hsv_image.at<Vec3b>(i, j)[0] >= 0 && hsv_image.at<Vec3b>(i, j)[0] <= 180)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 0 && hsv_image.at<Vec3b>(i, j)[1] <= 255)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 0 && hsv_image.at<Vec3b>(i, j)[2] <= 46)) {
                num_black++;
            }
            //{ "grey",0,0,46,180,43,220 }
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 0 && hsv_image.at<Vec3b>(i, j)[0] <= 180)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 0 && hsv_image.at<Vec3b>(i, j)[1] <= 43)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 46 && hsv_image.at<Vec3b>(i, j)[2] <= 220)) {
                num_grey++;
            }
            // { "white",0,0,221,180,30,255 }
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 0 && hsv_image.at<Vec3b>(i, j)[0] <= 180)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 0 && hsv_image.at<Vec3b>(i, j)[1] <= 30)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 221 && hsv_image.at<Vec3b>(i, j)[2] <= 255)) {
                num_white++;
            }
            //{ "red", 156, 43, 46, 180, 255, 255 }
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 156 && hsv_image.at<Vec3b>(i, j)[0] <= 180)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 43 && hsv_image.at<Vec3b>(i, j)[1] <= 255)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 46 && hsv_image.at<Vec3b>(i, j)[2] <= 255)) {
                num_red++;
            }
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 0 && hsv_image.at<Vec3b>(i, j)[0] <= 10)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 43 && hsv_image.at<Vec3b>(i, j)[1] <= 255)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 46 && hsv_image.at<Vec3b>(i, j)[2] <= 255)) {
                num_red++;
            }
            //{ "orange",11,43,46,25,255,255 }
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 11 && hsv_image.at<Vec3b>(i, j)[0] <= 25)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 43 && hsv_image.at<Vec3b>(i, j)[1] <= 255)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 46 && hsv_image.at<Vec3b>(i, j)[2] <= 255)) {
                num_orange++;
            }
            // { "yellow", 26, 43, 46, 34, 255, 255 }
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 26 && hsv_image.at<Vec3b>(i, j)[0] <= 34)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 43 && hsv_image.at<Vec3b>(i, j)[1] <= 255)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 46 && hsv_image.at<Vec3b>(i, j)[2] <= 255)) {
                num_yellow++;
            }
            //{ "green",35,43,46,99,255,255 },
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 35 && hsv_image.at<Vec3b>(i, j)[0] <= 99)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 43 && hsv_image.at<Vec3b>(i, j)[1] <= 255)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 46 && hsv_image.at<Vec3b>(i, j)[2] <= 255)) {
                num_green++;
            }
            //{ "blue",100,43,46,124,255,255 },
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 100 && hsv_image.at<Vec3b>(i, j)[0] <= 124)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 43 && hsv_image.at<Vec3b>(i, j)[1] <= 255)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 46 && hsv_image.at<Vec3b>(i, j)[2] <= 255)) {
                num_blue++;
            }
            //  { "purple",125,43,46,155,255,255 }
            else if ((hsv_image.at<Vec3b>(i, j)[0] >= 125 && hsv_image.at<Vec3b>(i, j)[0] <= 155)
                && (hsv_image.at<Vec3b>(i, j)[1] >= 43 && hsv_image.at<Vec3b>(i, j)[1] <= 255)
                && (hsv_image.at<Vec3b>(i, j)[2] >= 46 && hsv_image.at<Vec3b>(i, j)[2] <= 255)) {
                num_purple++;
            }
        }
    }

    record.insert(make_pair((char*)"black", (float)num_black / area));
    record.insert(make_pair((char*)"grey", (float)num_grey / area));
    record.insert(make_pair((char*)"white", (float)num_white / area));
    record.insert(make_pair((char*)"red", (float)num_red / area));
    record.insert(make_pair((char*)"orange", (float)num_orange / area));
    record.insert(make_pair((char*)"yellow", (float)num_yellow / area));
    record.insert(make_pair((char*)"green", (float)num_green / area));
    record.insert(make_pair((char*)"blue", (float)num_blue / area));
    record.insert(make_pair((char*)"purple", (float)num_purple / area));
    //(float)num / (float)(hsv_image.rows * hsv_image.cols);
    return;
}
/*
在图片里查找指定颜色的比例
*/
void Mat_color_Find(char* qimage)
{
    Mat image = imread(qimage);//将图片加载进来
    if (image.empty())
    {
        cout << "could not load image...\n" << endl;
        return;
    }
    Mat hsv_image;
    cvtColor(image, hsv_image, CV_BGR2HSV);

    hsv_percentage(hsv_image);
    //rat = (float)num / (float)(hsv_image.rows * hsv_image.cols);
    /*for (auto it = temp.begin(); it != temp.end(); it++) {
        cout << it->first << " " << it->second << endl;
    }*/
    //Hsv* Create();
    return;
}

本来我想直接,传unordered_map,但是,不同语言直接,无法之间传递不同的数据结构,对于C#调用C++,我采用的是结构体数组的方法。因为,我有9种颜色,一个结构体里面变量太多,所以,传递一个结构体数组即可。这里,主要介绍一下,结构体数组的传递方法:

//首先构建一个结构体
typedef struct {
    char color[32];//为什么不传string,因为,从c#与c++数据对应关系不一样,直接传string,c#找不到内存地址
    float percentage;
}Hsv;
//类
Triple* triple;
//返回结构体的指针地址,如果是数组,这个指针得加,不然,c#里面打印乱码
extern "C" __declspec(dllexport) Hsv * Create() {
    //Hsv hsv1[9];
    Hsv* hsv = (Hsv*)malloc(sizeof(Hsv) * 9);//就是这里得 * 9,因为,一个结构体是(Hsv*)malloc(sizeof(Hsv)),9种颜色偏移9
    //triple = new Triple();
    //数组初始化
    int i = 0;
    for (auto it = record.begin(); it != record.end(); it++) {
        //cout << it->first << " " << it->second << endl;
        triple = new Triple(it->first,it->second);
        strcpy_s(hsv[i].color, triple->Getcolor());
        hsv[i].percentage = triple->Getpercentage();
        i++;
    }
    return hsv;
    
}

(4)在源文件文件夹下新建模块定义文件(.def),输入以下内容:

LIBRARY hsv_percentage
EXPORTS Mat_color_Find
EXPORTS hsv_percentage
EXPORTS Create

(5)生成解决方案,有问题看这里

C#调用dll文件

(1)新建一个C#项目:
HSV
(2)把hsv_percentage.dll文件复制到该工程的Debug目录下:

hsv
(3)在C#文件中引用该 .dll 文件,代码如下:

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace ConsoleApp7
{
    class Program
    {
        
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct Triple
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string color;
            public float percentage;
        };
        [DllImport("hsv_percentage.dll")]
        public static extern bool Mat_color_Find(string qimage);
        [DllImport("hsv_percentage.dll")]
        public static extern IntPtr Create();
        
        public static Dictionary<string, float> CalcColorHist(string picpath) {
            Dictionary<string, float> color_temp = new Dictionary<string, float>();
            Mat_color_Find(picpath);
            int workStationCount = 9;
            int size = Marshal.SizeOf(typeof(Triple));
            //IntPtr infosIntptr = Marshal.AllocHGlobal(size * workStationCount);
            Triple[] triples = new Triple[workStationCount];

            for (int i = 0; i < workStationCount; i++)
            {
                IntPtr ptr = Create() + i * size;
                triples[i] = (Triple)Marshal.PtrToStructure(ptr, typeof(Triple));
                /*Console.WriteLine(triples[i].color);
                Console.WriteLine(triples[i].percentage);*/
                color_temp.Add(triples[i].color, triples[i].percentage);
            }
            foreach (KeyValuePair<string, float> kvp in color_temp)
            {
                Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
            }
            Console.ReadKey();
            return color_temp;

        }
        static void Main(string[] args)
        {
            string s1 = "C:/Users/wenhaofu/Desktop/picture/2021-07-01.png";
            CalcColorHist(s1);
            
        }
    }
}

(5)点击运行:
test

一些问题

关于c#中找不到函数的问题,你还需要包含opencv_world410d.dll

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值