0.
昨天有人问我,如何进行把人脸图片上传到服务器,然后与服务器中的一张人脸图片进行比对,判断是不是同一个人。
然后我自己不可能完全按照他的想法,只取其精华,我的想法是,本地有两张图片,然后通过post方法调用一个接口,然后获取获取返回值,然后判断是不是同一个人,那么这种接口真的有吗?
有。 https://console.faceplusplus.com.cn/documents/4887586
由接口可知,我们必须post带4个参数,2个string和2个file(本地两张图片),且接口文档也说了要用mutipart/form-data方式,且file要以二进制方式。(其它限制条件之后说)
一开始觉得很简单,应为之前用java做的类似的post。
且这里有java的解决方案: https://blog.csdn.net/scookiem/article/details/79409608
但是c#里面好像没有封装的 mutipart/form-data的post的方法啊,那我这几个参数要如何post,不几啊。
所以在post我们的4个参数之前,我们有必要熟悉 http的mutipart/form-data的post请求分析,既然没有封装的方法,那我们自己模拟表单提交数据就OK了。
这里直接看一篇教程就懂了:https://www.cnblogs.com/yinq/p/6045995.html
另外一篇详细点:https://www.cnblogs.com/herenzhiming/articles/6841969.html
其实就是请求的信息是按照一定的格式排版的,我们自己模拟提交,只要数据按照这个格式排版就行了(所以你可以自己去封装一个完美的方法啦!!!)
1.我们的代码如下:
private void HttpPostData() {
//定义边界符
var boundary = "ThisIsLiuYan";
//结束标志
String end = "--" + boundary + "--";
byte[] end_bytes = Encoding.UTF8.GetBytes(end);
//下面要用的一个换行符号
String enter = "\r\n";
byte[] enter_bytes = Encoding.UTF8.GetBytes(enter);
//接口地址
String jiekou = @"https://api-cn.faceplusplus.com/facepp/v3/compare";
var webRequest = (HttpWebRequest)WebRequest.Create(jiekou);
webRequest.Method = "POST";
webRequest.KeepAlive = true;
//设置边界符 和 ContentType
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
//保存我们请求的数据--按照排版格式的顺序
MemoryStream stream = new MemoryStream();
//2个string参数
String formate =
"--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}\r\n";
String onekey = String.Format(formate, "api_key", "你的key");
String twokey = String.Format(formate, "api_secret", "你的secret");
byte[] data = Encoding.UTF8.GetBytes(onekey);
stream.Write(data, 0, data.Length); //
data = Encoding.UTF8.GetBytes(twokey);
stream.Write(data, 0, data.Length); //
//2个file参数
String fmt =
"--" + boundary + "\r\n" +
"Content-Type:application/octet-stream" + "\r\n" +
"Content-Disposition: form-data; filename=\"{1}\"; name=\"{0}\"" +
"\r\n\r\n";
String threeKey = String.Format(fmt, "image_file1", "444.png");
String fourKey = String.Format(fmt, "image_file2", "555.png");
String one = @"G:\新建文件夹\444.png";
String two = @"G:\新建文件夹\555.png";
FileStream onefile = File.OpenRead(one);
FileStream twofile = File.OpenRead(two);
int one_lenth = (int)onefile.Length;
int two_lenth = (int)twofile.Length;
byte[] one_byte = new byte[one_lenth];
byte[] two_byte = new byte[two_lenth];
onefile.Read(one_byte, 0, one_lenth);
twofile.Read(two_byte, 0, two_lenth);
onefile.Close();
twofile.Close();
data = Encoding.UTF8.GetBytes(threeKey);
stream.Write(data, 0, data.Length);
stream.Write(one_byte, 0, one_byte.Length);
stream.Write(enter_bytes, 0, enter_bytes.Length); //注意:这里有个换行
data = Encoding.UTF8.GetBytes(fourKey);
stream.Write(data, 0, data.Length);
stream.Write(two_byte, 0, two_byte.Length);
stream.Write(enter_bytes, 0, enter_bytes.Length); //注意:这里有换行和下面结束
stream.Write(end_bytes, 0, end_bytes.Length);
webRequest.ContentLength = stream.Length; //应为这里要设置长度,所以前面要用memoryStream保存
Stream requestStream = webRequest.GetRequestStream();
stream.Position = 0L;
stream.CopyTo(requestStream);
stream.Close();
requestStream.Close();
try {
StreamReader sr = new StreamReader(webRequest.GetResponse().GetResponseStream()); //返回的数据
String responsString = sr.ReadToEnd();
sr.Close();
var jsonobj = JObject.Parse(responsString);
int v = (int)jsonobj["confidence"]; //只获取关键值,这里设置大于80即为同一人
if (v > 80) {
Label1.Text = "是同一个人";
}
else {
Label1.Text = "不是同一个人";
}
}
catch (Exception ee) {
Label1.Text = "" + ee.Message;
}
}
然后你自己调用这个方法,就可以达到效果了。不亏我一番琢磨。
2.
但是这个接口还是有缺陷的,图片大于2M会报错,图片的像素也有要求限制。如下
图片格式:JPG(JPEG),PNG
图片像素尺寸:最小 48*48 像素,最大 4096*4096 像素
图片文件大小:2MB
最小人脸像素尺寸: 系统能够检测到的人脸框为一个正方形,正方形边长的最小值为 150 像素。