c#调c++,用opencv+dlib识别照片中的人脸并返回结果图片

c#调c++,用opencv+dlib识别照片中的人脸并返回结果图片
c++部分代码如下

#include <fstream>  
#include <string>  
#include <iostream>  

#include "dlib/image_processing/frontal_face_detector.h"
#include "dlib/image_processing/render_face_detections.h"
#include "dlib/image_processing.h"
#include "dlib/gui_widgets.h"
#include "dlib/image_io.h"
 
#include <opencv/cv.h>
#include<opencv2/opencv.hpp>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <dlib/opencv.h>
#include <dlib/timer.h>

 
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <stdio.h>
 
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)//注意decl前面是两个下划线
#else
#define MYDLL_API __declspec(dllimport)
#endif


using namespace dlib;
using namespace std;
using namespace cv;
using namespace std;

static frontal_face_detector detector;
static shape_predictor sp;
static int isIni = 0; 
std::string TCHAR2STRING(TCHAR *STR)
{
	int iLen = WideCharToMultiByte(CP_ACP, 0, STR, -1, NULL, 0, NULL, NULL);
	char* chRtn = new char[iLen * sizeof(char)];
	WideCharToMultiByte(CP_ACP, 0, STR, -1, chRtn, iLen, NULL, NULL);
	std::string str(chRtn);
	return str;
}
//获取当前目录下的shape_predictor_68_face_landmarks.dat文件路径
std::string getDataPath() {
	TCHAR szPath[MAX_PATH] = { 0 };
	if (!GetModuleFileName(NULL, szPath, MAX_PATH)) {
		return 0;
	}
	int i = MAX_PATH - 1;
	while (szPath[i] != '\\') {
		i--;
	}
	i++;
	string name = "shape_predictor_68_face_landmarks.dat";
	for (int j = 0; j < name.length(); j++) {
		szPath[i] = name[j];
		i++;
	}
	szPath[i] = 0;
	return TCHAR2STRING(szPath);
}

void ini() {
	if (isIni == 0) {
		detector = get_frontal_face_detector();
		deserialize(getDataPath()) >> sp;
	}
	isIni = 1;
}
//bimage图片的数组,nH图片的高度,nW图片的宽度,stride图片的stride值,data返回的图片内容,size图片内容长度,count识别的人脸个数
MYDLL_API void FindFaces(BYTE * bimage, int nH, int nW, int stride, uchar *data, size_t &size, uint &count);

template <typename T, long NR, long NC, typename mm, typename l>
void dlibMatrix2cvBGR(cv::Mat &dest, const dlib::matrix<T, NR, NC, mm, l> &src)
{
	dlib::matrix<dlib::bgr_pixel> tmp;
	dlib::assign_image(tmp, src);
	dest = dlib::toMat(tmp).clone();
}
void  FindFaces(BYTE* pImg, int nH, int nW, int stride, uchar *data, size_t &size,uint &count) {
	Mat image = Mat(nH, nW, CV_8UC3, pImg, stride).clone();
	ini();
	dlib::cv_image<bgr_pixel> dlib_img(image);
	std::vector<dlib::rectangle> dets = detector(dlib_img);
	std::vector<full_object_detection> shapes;
	if (dets.size() == 0)
	{
		count = 0;
		return;
	}
	count = dets.size();
	for (unsigned long j = 0; j < dets.size(); ++j)
	{ 
		full_object_detection shape = sp(dlib_img, dets[j]); 
		shapes.push_back(shape); 
	}
	dlib::array<array2d<bgr_pixel> > face_chips;
	extract_image_chips(dlib_img, get_face_chip_details(shapes, 100, 0.1), face_chips);
	cv::Mat src;
	dlibMatrix2cvBGR(src, tile_images(face_chips)); 
	std::vector<uchar> buf;
	cv::imencode(".bmp", src, buf); //将Mat以bmp格式存入内存中,转换为uchar数组
	size = buf.size();
	for each(uchar var in buf) //将buf拷贝到C#的输出byte[] 内存中
	{
		*data = var;
		data++;
	}

}

c#调用代码

 [DllImport("FaceSearch.dll", EntryPoint = "FindFaces", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
 public static extern void FindFaces(byte[] bimage, int nH, int nW, int stride, ref byte data, out ulong size,out uint count);


 Bitmap bmp = (Bitmap)Bitmap.FromFile(@"C:\Users\wu\Pictures\a.jpg");
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
            System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
            //Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;
            // Declare an array to hold the bytes of the bitmap. 
            int bytesLength = Math.Abs(bmpData.Stride) * bmp.Height;
            int imageWeidth = bmp.Width;
            int imageHeight = bmp.Height;
            //图像的Stride
            int imageStride = bmpData.Stride;
            byte[] buffer = new byte[bytesLength];
            // Copy the RGB values into the array.
            Marshal.Copy(ptr, buffer, 0, bytesLength);
            bmp.UnlockBits(bmpData);
            byte[] ptrData = new byte[2048 * 2048 * 3]; //尽可能大的byte[]
            ulong size = new ulong();
            GetMat(ref ptrData[0], out size); //将C++的内存数据转入C#的内存中
            uint count = 0;
            FindFaces(buffer, imageHeight, imageWeidth, imageStride,ref  ptrData[0], out size, out count);
            pictureBox1.Image = Image.FromStream(new MemoryStream(ptrData, 0, (int)size));
            label1.Text = count.ToString();

效果如下:
上送图片:
在这里插入图片描述
处理后显示的图片:
在这里插入图片描述

原创文章 4 获赞 0 访问量 673

猜你喜欢

转载自blog.csdn.net/weixin_42139362/article/details/104427129
今日推荐