VGGFace2是一个大规模人脸识别数据集。数据的来源是谷歌搜索引擎.数据标注了姿态、年龄、光照、种族和职业。
</img>
</img>
</img>
Q. Cao, L. Shen, W. Xie, O. M. Parkhi, A. Zisserman
VGGFace2: A dataset for recognising face across pose and age
International Conference on Automatic Face and Gesture Recognition, 2018.
#下载opencv源码
git clone https://github.com/opencv/opencv.git
cd opencv
git checkout remotes/origin/3.4
#下载extras源码
git clone https://github.com/opencv/opencv_extra.git
cd opencv_extra
git checkout remotes/origin/3.4
#编译安装
cd opencv
cmake .. -DPYTHON_DEFAULT_EXECUTABLE=/data/ruben/anaconda3/bin/python -DBUILD_opencv_python2=Off -DBUILD_opencv_python3=On -DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules -DCMAKE_BUILD_TYPE=RELEASE -DWITH_CUDA=ON -DENABLE_FAST_MATH=1 -DCUDA_FAST_MATH=1 -DWITH_CUBLAS=1 -DCUDA_GENERATION=Auto -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda
make -j12
sudo make install
sudo updatedb
locate OpenCVConfig.cmake
根据输出找出已经安装的opencv路径,然后卸载即可。
依次执行:
sudo dpkg -i cuda-repo-ubuntu1604_10.0.130-1_amd64.deb
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub`
sudo apt-get update
sudo apt-get install cuda
sudo apt-get install cuda-toolkit-8-0
即可。
sudo apt-get install libopenexr-dev
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DBUILD_PNG=OFF \
-DBUILD_TIFF=OFF \
-DBUILD_TBB=OFF \
-DBUILD_JPEG=OFF \
-DBUILD_JASPER=OFF \
-DBUILD_ZLIB=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_opencv_java=OFF \
-DBUILD_opencv_python2=ON \
-DBUILD_opencv_python3=OFF \
-DWITH_OPENCL=OFF \
-DWITH_OPENMP=OFF \
-DWITH_FFMPEG=ON \
-DWITH_GSTREAMER=OFF \
-DWITH_GSTREAMER_0_10=OFF \
-DWITH_CUDA=ON \
-DWITH_GTK=ON \
-DWITH_VTK=OFF \
-DWITH_TBB=ON \
-DWITH_1394=OFF \
-DWITH_OPENEXR=OFF \
-DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda \
-DCUDA_ARCH_BIN='3.0 3.5 5.0 6.0 6.2' \
-DCUDA_ARCH_PTX="" \
-DINSTALL_C_EXAMPLES=ON \
-DINSTALL_TESTS=OFF \
-DOPENCV_TEST_DATA_PATH=../opencv_extra/testdata \
../opencv
在开发过程中,android作为客户端,flask作为服务端。图片的通信通过base64字符串的形式进行,所以在服务器端通常需要进行解码。
解码过程中核心的包包括:cv2 io base64 imageio
.
下面是使用方法:
from imageio import imread
import cv2
import io
import base64
bstring='R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7'
# reconstruct image as an numpy array
img = imread(io.BytesIO(base64.b64decode(bstring)))
cv2_img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
cv2.imshow("reconstructed.jpg", cv2_img)
cv2.waitKey(0)
在android中通过http post方法传递数据,核心的包是:
java.net.HttpURLConnection
另外还有是http header的设置,以及post中参数的设置。
详细的可以参考下面的代码:
package com.rubenxiao.blog;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
/**
* Created by ruben on 18-9-18.
*/
public class HttpUtils {
public static String submitPostData(Map<String, String> params, String encode) throws MalformedURLException {
/**
* 发送POST请求到服务器并返回服务器信息
* @param params 请求体内容
* @param encode 编码格式
* @return 服务器返回信息
*/
byte[] data = getRequestData(params, encode).toString().getBytes();
URL url = new URL("http://172.16.1.226:5557/upload");
HttpURLConnection httpURLConnection = null;
try{
httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.setConnectTimeout(3000); // 设置连接超时时间
httpURLConnection.setDoInput(true); // 打开输入流,以便从服务器获取数据
httpURLConnection.setDoOutput(true); // 打开输出流,以便向服务器提交数据
httpURLConnection.setRequestMethod("POST"); // 设置以POST方式提交数据
httpURLConnection.setUseCaches(false); // 使用POST方式不能使用缓存
// 设置请求体的类型是文本类型
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// 设置请求体的长度
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(data.length));
// 获得输入流,向服务器写入数据
OutputStream outputStream = new BufferedOutputStream(httpURLConnection.getOutputStream());
outputStream.write(data);
outputStream.flush(); // 重要!flush()之后才会写入
int response = httpURLConnection.getResponseCode(); // 获得服务器响应码
if (response == HttpURLConnection.HTTP_OK) {
InputStream inputStream = httpURLConnection.getInputStream();
return dealResponseResult(inputStream); // 处理服务器响应结果
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpURLConnection.disconnect();
}
return "";
}
/**
* 封装请求体信息
* @param params 请求体内容
* @param encode 编码格式
* @return 请求体信息
*/
public static StringBuffer getRequestData(Map<String, String> params, String encode) {
StringBuffer stringBuffer = new StringBuffer(); //存储封装好的请求体信息
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
stringBuffer.append(entry.getKey())
.append("=")
.append(URLEncoder.encode(entry.getValue(), encode))
.append("&");
}
stringBuffer.deleteCharAt(stringBuffer.length() - 1); // 删除最后一个"&"
} catch (Exception e) {
e.printStackTrace();
}
return stringBuffer;
}
/**
* 处理服务器的响应结果(将输入流转换成字符串)
* @param inputStream 服务器的响应输入流
* @return 服务器响应结果字符串
*/
public static String dealResponseResult(InputStream inputStream) {
String resultData = null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int len = 0;
try {
while ((len = inputStream.read(data)) != -1) {
byteArrayOutputStream.write(data, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
resultData = new String(byteArrayOutputStream.toByteArray());
return resultData;
}
}
使用方法:
String imgString = Base64.encodeToString(bytes, Base64.NO_WRAP);
Map<String, String> params = new HashMap<String, String>();
String post_result = null;
params.put("base64", imgString);
try {
post_result = HttpUtils.submitPostData(params, "utf-8");
Log.i("POST_RESULT", post_result);
} catch (MalformedURLException e) {
e.printStackTrace();
}
import reprlib
reprlib.repr(set('supercalifragilisticexpialidocious'))
#"{'a', 'c', 'd', 'e', 'f', 'g', ...}"
import pprint
t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta',
'yellow'], 'blue']]]
pprint.pprint(t, width=30)
#[[[['black', 'cyan'],
# 'white',
# ['green', 'red']],
# [['magenta', 'yellow'],
# 'blue']]]
import textwrap
doc = """The wrap() method is just like fill() except that it returns
a list of strings instead of one big string with newlines to separate
the wrapped lines."""
print(textwrap.fill(doc, width=40))
#The wrap() method is just like fill()
#except that it returns a list of strings
#instead of one big string with newlines
#to separate the wrapped lines.
import locale
locale.setlocale(locale.LC_ALL, 'English_United States.1252')
'English_United States.1252'
conv = locale.localeconv() # get a mapping of conventions
x = 1234567.8
locale.format("%d", x, grouping=True)
#'1,234,567'
locale.format_string("%s%.*f", (conv['currency_symbol'],
conv['frac_digits'], x), grouping=True)
#'$1,234,567.80'
import threading, zipfile
import time
class TestThread(threading.Thread):
def __init__(self, instring):
threading.Thread.__init__(self)
self.out=instring
def run(self):
time.sleep(10)
print(self.out)
background = TestThread('test string...')
background.start()
print('The main program continues to run in foreground.')
background.join() # Wait for the background task to finish
print('Main program waited until background was done.')
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
import bisect
scores = ['a','aa','aaa','aaaaa','aaaaaaaaaa']
bisect.insort(scores, 'aaaa')
print(scores)
#['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaaaaaa']
from collections import deque
d = deque(["task1", "task2", "task3"])
d.append("task4")
print("Handling", d.popleft(),d.pop())
#Handling task1 task4
from array import array
a = array('H', [4000, 10, 700, 22222])
print(sum(a))
print(a[1:3])
#26932
array('H', [10, 700])
from heapq import heapify, heappop, heappush
data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
heapify(data) # rearrange the list into heap order
heappush(data, -5) # add a new entry
[heappop(data) for i in range(3)] # fetch the three smallest entries
#[-5, 0, 1]
from decimal import *
round(Decimal('0.70') * Decimal('1.05'), 2)
#Decimal('0.74')
round(.70 * 1.05, 2)
#0.73
import os
os.getcwd()#返回当前的工作目录
#'/home/ruben'
os.chdir('/server/accesslogs') #改变当前工作目录
os.system('mkdir today') #新建目录
dir(os)
#['CLD_CONTINUED', 'CLD_DUMPED', 'CLD_EXITED', 'CLD_TRAPPED', 'DirEntry', 'EX_CANTCREAT', 'EX_CONFIG', 'EX_DATAERR', 'EX_IOERR',.......返回os的内置方法、内置变量等
help(os)
#返回os包的帮助信息:
os库包含的是许多关于操作系统的相关操作
import shutil
shutil.copyfile('data.db', 'archive.db')#拷贝文件
shutil.move('/build/executables', 'installdir')#移动文件
shutils是关于文件相关的操作
import glob
glob.glob('*.py')#枚举文件
#['primes.py', 'random.py', 'quote.py']
glob是关于文件或文件夹的列举操作
import sys
print(sys.argv)
#['demo.py', 'one', 'two', 'three']
sys.stderr.write('Warning, log file not found starting a new one\n')#命令行输出错误信息
sys.exit()#退出脚本
sys是关于命令行中参数的获取,比如python demo.py one two three
。获取到的第一个参数是代码文件名,第二到第四个参数是用于输入的自定义参数。
import re
re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
#['foot', 'fell', 'fastest']
re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
#'cat in the hat'
'tea for too'.replace('too', 'two')
#'tea for two'
数学操作
import math
math.cos(math.pi / 4)
#0.70710678118654757
math.log(1024, 2)
#10.0
随机数的产生
import random
random.choice(['apple', 'pear', 'banana'])
#'apple'
random.sample(range(100), 10) # sampling without replacement
#[30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
random.random() # random float
#0.17970987693706186
random.randrange(6) # random integer chosen from range(6)
#4
统计相关操作
import statistics
data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
statistics.mean(data)
#1.6071428571428572
statistics.median(data)
#1.25
statistics.variance(data)
#1.3720238095238095
网络访问
from urllib.request import urlopen
with urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl') as response:
for line in response:
line = line.decode('utf-8') # Decoding the binary data to text.
if 'EST' in line or 'EDT' in line: # look for Eastern Time
print(line)
#<BR>Nov. 25, 09:43:32 PM EST
import smtplib
server = smtplib.SMTP('localhost')
server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
"""
To: jcaesar@example.org
From: soothsayer@example.org
Beware the Ides of March.
""")
server.quit()
时间相关操作
from datetime import date
now = date.today()
now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
#'09-11-18. 11 Sep 2018 is a Tuesday on the 11 day of September.'
datetime.date(2018, 11, 9)
birthday = date(1964, 7, 31)
age = now - birthday
age.days
#14368
文件或字符压缩
import zlib
s = b'witch which has which witches wrist watch'
len(s)
#41
t = zlib.compress(s)
len(t)
#37
zlib.decompress(t)
#b'witch which has which witches wrist watch'
zlib.crc32(s)
#226805979
性能测试
from timeit import Timer
Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
#0.57535828626024577
Timer('a,b = b,a', 'a=1; b=2').timeit()
#0.54962537085770791
文档测试
def average(values):
"""Computes the arithmetic mean of a list of numbers.
>>> print(average([20, 30, 70]))
40.0
"""
return sum(values) / len(values)
import doctest
doctest.testmod()
单元测试
import unittest
class TestStatisticalFunctions(unittest.TestCase):
def test_average(self):
self.assertEqual(average([20, 30, 70]), 40.0)
self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
with self.assertRaises(ZeroDivisionError):
average([])
with self.assertRaises(TypeError):
average(20, 30, 70)
unittest.main()
上面介绍的是一些基本的标准库,还有提供rpc服务的xmlrpc,邮件服务的email,json解析的json库,sqlite数据库的sqlite3…等等,这些标准库完成了许多标准化操作。另外还有更多的第三方库这里就不一一列举了。
之前的文章介绍了module
和package
。
我们知道package
是以文件夹的形式组织的,每个文件夹下的.py
文件称之为module
。而class
在每个.py
文件中。
一个简单的class
示例如下所示:
class MyClass:
"""A simple example class"""
i = 12345#成员变量
def f(self):#成员方法
return 'hello world'
要实例化一个class
可以通过new instance=ClassName()
的方式实例化。而成员变量和成员方法可以通过instance.name
或者instance.function_name
的方式调用。
上述MyClass的示例如下:
c=MyClass()
print(c.i)
#12345
print(c.f())
#hello world
更复杂一点的例子:
class Complex:
i=[]
def __init__(self, realpart, imagpart):
self.r = realpart
self.i.append(imagpart)
调用方式:
x = Complex(3.0, -4.5)
print(x.r,x.i)
#3.0 [-4.5]
xx = Complex(3.0, -2)
print(xx.r,xx.i)
#3.0 [-4.5, -2]
这里添加了__init__()
内置方法用于初始化class
中的成员变量。这里可以看到类Complex
的两个实例x
和xx
中成员变量i
的输出是不同的。关于类中的变量作用域将在下文介绍,暂且不表。
首先让我们运行下面的代码:
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
spam='spam'
scope_test()
print("In global scope:", spam)
得到的输出是:
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
下面将对上述代码进行分析:
首先定义了全局变量spam
,并赋值‘spam’。
接着实例化类scope_test()
,执行类中的代码:
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test
,并将局部变量spam
赋值为test spam
。do_local()
中spam
变量的作用域是do_local()
方法,因而只是创建了一个本地变量,并赋值为local spam
,但在方法之外失效。spam
变量是第一步中的局部spam
变量,输出即是test spam
。do_nonlocal()
方法中将spam
变量通过nonlocal
关键字表示使用的是局部变量,因而此时的spam是第一步声明的spam
局部变量。此时spam
变量的值变为nonlocal spam
。nonlocal spam
do_global()
中通过global
关键字声明使用的spam
是全局变量,因而全局变量spam的值修改为global spam
nonlocal spam
最后回到最外层的代码:
print("In global scope:", spam)
这里的变量spam
是全局变量,根据上面的分析可以知道spam
已经被修改为global spam
,因而输出是global spam
。
以上介绍了python
中class
的基本使用方法,之后介绍了class
中变量的作用域范围,了解之后基本就能掌握class
的基本使用方法了。
在编译某些项目的时候发现对cmake的版本要求是3.11以上,但是通过update和upgrade的操作之后cmake的版本还是停留在3.5的状态,之后按照网上的一些方法依然没有成功。最后使用源码的方法安装成功了。具体的操作过程如下:
打开cmake官网,或者直接点击 cmake3.12-linux版本地址下载。
注意本文使用的是3.12版本,在安装的时候使用跟自己下载的版本对应的本地路径。
tar -xvf cmake-3.12.1.tar.gz
cd cmake-3.12.1
cmake .
make -j8
sudo make install
使用:
sudo update-alternatives --install /usr/bin/cmake cmake /usr/local/bin/cmake 1 --force
可以看到输出的是:
cmake version 3.12.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).
即可~