人脸识别之VGGFace2


VGGFace2是一个大规模人脸识别数据集。数据的来源是谷歌搜索引擎.数据标注了姿态、年龄、光照、种族和职业。

数据的特色

</img>

  • 9,000+特性,包含年龄、种族、职业等

</img>

  • 33亿张人脸:所有人脸都是在自然条件下的,并且经过了姿态、情绪验证,分别有不同光照、遮挡条件。

</img>

  • 每个类别平均有362张图片,图片在每个类别下的分布均匀,少的有87,多的有862张。

数据和模型下载链接

论文

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.

阅读全文 »


ubuntu中源码编译安装cuda版opencv


安装

#下载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

可能遇到的问题

  • 1.卸载opencv 在安装之前需要卸载之前安装的opencv,执行下面的命令:
    sudo updatedb
    locate OpenCVConfig.cmake
    

    根据输出找出已经安装的opencv路径,然后卸载即可。

  • 2.nvcc fatal: Unsupported gpu architecture ‘compute_60’ 这个问题的原因是需要更新cuda,打开链接link,保存到本地路径。

依次执行:

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 

即可。

  • 3.fatal error: ImfChromaticities.h: No such file or directory
sudo apt-get install libopenexr-dev
  • 4.完整的cmake参考
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

阅读全文 »


python将base64字符串转换为cv2中的numpy.ndarray


在开发过程中,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方法上传数据


在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();
    }

阅读全文 »


python中的标准库(2)


格式化输出

  • reprlib
    import reprlib
    reprlib.repr(set('supercalifragilisticexpialidocious'))
    #"{'a', 'c', 'd', 'e', 'f', 'g', ...}"
    
  • pprint
import pprint
t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta',
     'yellow'], 'blue']]]
pprint.pprint(t, width=30)
#[[[['black', 'cyan'],
#   'white',
#   ['green', 'red']],
#  [['magenta', 'yellow'],
#   'blue']]]
  • textwrap
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.
  • locale
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')

列表操作

  • bisect
    import bisect
    scores = ['a','aa','aaa','aaaaa','aaaaaaaaaa']
    bisect.insort(scores, 'aaaa')
    print(scores)
    #['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaaaaaa']
    
  • deque
    from collections import deque
    d = deque(["task1", "task2", "task3"])
    d.append("task4")
    print("Handling", d.popleft(),d.pop())
    #Handling task1 task4
    
  • array
    from array import array
    a = array('H', [4000, 10, 700, 22222])
    print(sum(a))
    print(a[1:3])
    #26932
    array('H', [10, 700])
    
  • heapq
    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]
    

浮点数

  • decimal
    from decimal import *
    round(Decimal('0.70') * Decimal('1.05'), 2)
    #Decimal('0.74')
    round(.70 * 1.05, 2)
    #0.73
    

阅读全文 »


python中的标准库(1)


  • os库
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库包含的是许多关于操作系统的相关操作

  • shutil库
import shutil
shutil.copyfile('data.db', 'archive.db')#拷贝文件
shutil.move('/build/executables', 'installdir')#移动文件

shutils是关于文件相关的操作

  • glob
import glob
glob.glob('*.py')#枚举文件
#['primes.py', 'random.py', 'quote.py']

glob是关于文件或文件夹的列举操作

  • sys
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。获取到的第一个参数是代码文件名,第二到第四个参数是用于输入的自定义参数。

  • re
  • 正则操作
    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'
    
  • math

数学操作

import math
math.cos(math.pi / 4)
#0.70710678118654757
math.log(1024, 2)
#10.0
  • random

随机数的产生

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
  • statistics

统计相关操作

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
  • urllib

网络访问

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
  • smtplib
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()
  • datetime

时间相关操作

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
  • zlib,gzip, bz2, lzma, zipfile,tarfile.

文件或字符压缩

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
  • timeit

性能测试

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
  • doctest

文档测试

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()   
  • unittest

单元测试

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…等等,这些标准库完成了许多标准化操作。另外还有更多的第三方库这里就不一一列举了。

阅读全文 »


python中的class


之前的文章介绍了modulepackage

我们知道package是以文件夹的形式组织的,每个文件夹下的.py文件称之为module。而class在每个.py文件中。

最基本的class

一个简单的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的两个实例xxx中成员变量i的输出是不同的。关于类中的变量作用域将在下文介绍,暂且不表。

class中变量的作用域

首先让我们运行下面的代码:

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)
  • 第一个变量spam的作用域是类scope_test,并将局部变量spam赋值为test spam
  • do_local()spam变量的作用域是do_local()方法,因而只是创建了一个本地变量,并赋值为local spam,但在方法之外失效。
  • 此时,print方法打印的spam变量是第一步中的局部spam变量,输出即是test spam
  • do_nonlocal()方法中将spam变量通过nonlocal关键字表示使用的是局部变量,因而此时的spam是第一步声明的spam局部变量。此时spam变量的值变为nonlocal spam
  • 按照上一步分系,此时打印的值应该是nonlocal spam
  • do_global()中通过global关键字声明使用的spam是全局变量,因而全局变量spam的值修改为global spam
  • 这里输出的是局部变量spam,因而输出是nonlocal spam

最后回到最外层的代码:

print("In global scope:", spam)

这里的变量spam是全局变量,根据上面的分析可以知道spam已经被修改为global spam,因而输出是global spam

以上介绍了pythonclass的基本使用方法,之后介绍了class中变量的作用域范围,了解之后基本就能掌握class的基本使用方法了。

阅读全文 »


如何更新ubuntu中cmake版本


在编译某些项目的时候发现对cmake的版本要求是3.11以上,但是通过update和upgrade的操作之后cmake的版本还是停留在3.5的状态,之后按照网上的一些方法依然没有成功。最后使用源码的方法安装成功了。具体的操作过程如下:

1.下载cmake

打开cmake官网,或者直接点击 cmake3.12-linux版本地址下载。

2.安装

注意本文使用的是3.12版本,在安装的时候使用跟自己下载的版本对应的本地路径。

tar -xvf cmake-3.12.1.tar.gz
cd cmake-3.12.1
cmake .
make -j8
sudo make install

3.更新

使用:

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).

即可~

阅读全文 »