C#调dlib,opencv传bitbmp图片
c++代码
思路是c#调摄相头拍照,将照片传给c++写的dll进行人脸识别处理再按返回的结果画框。这里c++的返回是一个字符串,以逗号分隔的坐标点,这个原型主要是为了后面做返回json串做准备的。
c++的dll项目要写一个def文件,内容为:
LIBRARY
EXPORTS
facedetect
c++代码内容为:
...
#pragma once
#ifdef DLLEXAM_EXPORTS
#define DLLEXAM_API __declspec(dllexport)
#else
#define DLLEXAM_API __declspec(dllimport)
#endif
DLLEXAM_API int facedetect(byte pImg[], int nH, int nW, int stride, char *output);
int facedetect(byte pImg[], int nH, int nW, int stride, char *output) {
Mat image = Mat(nH, nW, CV_8UC3, pImg, stride).clone();
dlib::cv_image<rgb_pixel> dlib_img(image);
frontal_face_detector detector = get_frontal_face_detector();
std::vector<rectangle> dets = detector(dlib_img);
int i = 0;
std::string ret = "";
for (int i = 0;i < dets.size() ;i++) {
rectangle r=dets[i];
ret.append(to_string(r.left()));
ret.append(",");
ret.append(to_string(r.top()));
ret.append(",");
ret.append(to_string(r.right()));
ret.append(",");
ret.append(to_string(r.bottom()));
ret.append(",");
}
strcpy(output, ret.c_str());
return 1;
}
c#代码:
...
[DllImport("DLINK.dll", EntryPoint = "facedetect", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
public static extern int facedetect(byte[] bimage, int nH, int nW, int stride, ref byte output);
Bitmap img = vispShoot.GetCurrentVideoFrame();//调摄相头拍照
if (img == null) return;
Bitmap bmp = null;
//将图像转换为24位rgb图像
if (img.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
{
bmp = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
}
}
else
{
bmp = img;
}
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[] ret = new byte[1000];
int count=0;
count= facedetect(buffer, imageHeight, imageWeidth, imageStride,ref ret[0] );
string strGet = System.Text.Encoding.Default.GetString(ret, 0, ret.Length); //将字节数组转换为字符串
MemoryStream ms = new MemoryStream();
byte[] imagedata = null;
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
imagedata = ms.GetBuffer();
//画个人脸框
if (count > 0)
{
String[] strp = strGet.Split(new char[] { ',' });
rectangle[] rects = new rectangle[count];
for (int i = 0; i < count; i++)
{
if (strp.Length < (i + 1) * 4) break;
int p = i * 4;
rects[i].left = Convert.ToInt32(strp[p]);
p++;
rects[i].top = Convert.ToInt32(strp[p]);
p++;
rects[i].right = Convert.ToInt32(strp[p]);
p++;
rects[i].bottom = Convert.ToInt32(strp[p]);
}
Graphics g = Graphics.FromImage(bmp);
for (int i = 0; i < count; i++)
{
g.DrawLine(new Pen(Color.Red, 2.0f), new Point(rects[i].left, rects[i].top), new Point(rects[i].left, rects[i].bottom));
g.DrawLine(new Pen(Color.Red, 2.0f), new Point(rects[i].left, rects[i].top), new Point(rects[i].right, rects[i].top));
g.DrawLine(new Pen(Color.Red, 2.0f), new Point(rects[i].left, rects[i].bottom), new Point(rects[i].right, rects[i].bottom));
g.DrawLine(new Pen(Color.Red, 2.0f), new Point(rects[i].right, rects[i].bottom), new Point(rects[i].right, rects[i].top));
}
}
pictureBox1.Image = bmp;