opencv计算机视觉学习笔记八

 

第九章 基于opencv的神经网络简介

1 人工神精网络ann

 

2 人工神精网络的结构

输入层

网络的输入数目

如动物有体重,长度,牙齿三个属性,网络则需要三个输入节点

中间层

 

输出层

与定义的类别数相同,如定义了猪,狗,猫,鸡,则输出层的数目为4

 

 

 

创建ANN常见规则

神经元数 位于输入/输出层之间, 接近输出层

较小的输入,神经元数=(输入+输出)/3*2

 

学习算法:

监督学习

非监督学习

强化学习

 

3 opencv中的ann

示例代码如下:


import cv2
import numpy as np

# 创建ann,MLP 是multilayer perceptron 感知器
ann = cv2.ml.ANN_MLP_create()
# 设置拓扑结构,通过数组来定义各层大小,分别对应输入/隐藏/输出
ann.setLayerSizes(np.array([9, 5, 9], dtype=np.uint8))
# 采用反向传播方式,还有一种方式ANN_MLP_RPROP,只有在有监督学习中才可以设置
ann.setTrainMethod(cv2.ml.ANN_MLP_BACKPROP)

# 有点类似于向量机svm的 train函数
ann.train(np.array([[1.2, 1.3, 1.9, 2.2, 2.3, 2.9, 3.0, 3.2, 3.3]], dtype=np.float32)# 对应9个输入数据
          cv2.ml.ROW_SAMPLE# 如果提供以下几个参数就是有监督学习
          np.array([[0, 0, 0, 0, 0, 1, 0, 0, 0]], dtype=np.float32))  # 输出层大小为9
print(ann.predict(np.array([[1.4, 1.5, 1.2, 2., 2.5, 2.8, 3., 3.1, 3.8]], dtype=np.float32)))

# 输出结果为:
# (5.0, #类标签
#  array([[-0.06419383, -0.13360272, -0.1681568 , -0.18708915,  0.0970564 ,  #输入数据属于每个类的概率
#        0.89237726,  0.05093023,  0.17537238,  0.13388439]], dtype=float32))

 

基于ann的动物分类

示例代码如下:


import cv2
import numpy as np
from random import randint

# 创建ann
animals_net = cv2.ml.ANN_MLP_create()
# 设定train函数为弹性反向传播
animals_net.setTrainMethod(cv2.ml.ANN_MLP_RPROP | cv2.ml.ANN_MLP_UPDATE_WEIGHTS)
animals_net.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM)
# 设置拓扑结构,通过数组来定义各层大小,分别对应输入/隐藏/输出
animals_net.setLayerSizes(np.array([3, 8, 4]))
# 指定ann的终止条件
animals_net.setTermCriteria((cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1))

"""
输入数组
weight, length, teeth
"""
"""
输出数组 狗 膺 海豚 龙
dog,eagle,dolphin and dragon
"""


def dog_sample():
    return [randint(5, 20), 1, randint(38, 42)]


def dog_class():
    return [1, 0, 0, 0]


def eagle_sample():
    return [randint(3, 13), 3, 0]


def eagle_class():
    return [0, 1, 0, 0]


def dolphin_sample():
    return [randint(30, 190), randint(5, 15), randint(80, 100)]


def dolphin_class():
    return [0, 0, 1, 0]


def dragon_sample():
    return [randint(1200, 1800), randint(15, 40), randint(160, 180)]


def dragon_class():
    return [0, 0, 0, 1]





"""
# 创建四类动物数据,每类5000个样本
SAMPLE = 5000
for x in range(0, SAMPLE):
    print("samples %d/%d" % (x, SAMPLE))
    animals_net.train(np.array([dog_sample()], dtype=np.float32),
                      cv2.ml.ROW_SAMPLE,
                      np.array([dog_class()], dtype=np.float32))

    animals_net.train(np.array([eagle_sample()], dtype=np.float32),
                      cv2.ml.ROW_SAMPLE,
                      np.array([eagle_class()], dtype=np.float32))

    animals_net.train(np.array([dolphin_sample()], dtype=np.float32),
                      cv2.ml.ROW_SAMPLE,
                      np.array([dolphin_class()], dtype=np.float32))

    animals_net.train(np.array([dragon_sample()], dtype=np.float32),
                      cv2.ml.ROW_SAMPLE,
                      np.array([dragon_class()], dtype=np.float32))

print(animals_net.predict(np.array([dog_sample()], dtype=np.float32)))
print(animals_net.predict(np.array([eagle_sample()], dtype=np.float32)))
print(animals_net.predict(np.array([dolphin_sample()], dtype=np.float32)))
print(animals_net.predict(np.array([dragon_sample()], dtype=np.float32)))
# 输出结果
# (1.0, array([[ 1.49817729,  1.60551953, -1.56444871, -0.04313202]], dtype=float32))
# (1.0, array([[ 1.49817729,  1.60551953, -1.56444871, -0.04313202]], dtype=float32))
# (1.0, array([[ 1.49817729,  1.60551953, -1.56444871, -0.04313202]], dtype=float32))
# (1.0, array([[ 1.42620921,  1.5461663 , -1.4097836 ,  0.07277301]], dtype=float32))
"""

# 训练周期
def record(sample, classification):
    return (np.array([sample], dtype=np.float32), np.array([classification], dtype=np.float32))

records = []
RECORDS = 5000
for x in range(0, RECORDS):
    records.append(record(dog_sample(), dog_class()))
    records.append(record(eagle_sample(), eagle_class()))
    records.append(record(dolphin_sample(), dolphin_class()))
    records.append(record(dragon_sample(), dragon_class()))

EPOCHS = 2
for e in range(0, EPOCHS):
    print("Epoch %d:" % e)
    for t, c in records:
        animals_net.train(t, cv2.ml.ROW_SAMPLE, c)

TESTS = 100
dog_results = 0
for x in range(0, TESTS):
    clas = int(animals_net.predict(np.array([dog_sample()], dtype=np.float32))[0])
    print("class: %d" % clas)
    if (clas) == 0:
        dog_results += 1
eagle_results = 0
for x in range(0, TESTS):
    clas = int(animals_net.predict(np.array([eagle_sample()], dtype=np.float32))[0])
    print("class: %d" % clas)
    if (clas) == 1:
        eagle_results += 1

dolphin_results = 0
for x in range(0, TESTS):
    clas = int(animals_net.predict(np.array([dolphin_sample()], dtype=np.float32))[0])
    print("class: %d" % clas)
    if (clas) == 2:
        dolphin_results += 1

dragon_results = 0
for x in range(0, TESTS):
    clas = int(animals_net.predict(np.array([dragon_sample()], dtype=np.float32))[0])
    print("class: %d" % clas)
    if (clas) == 3:
        dragon_results += 1

print("Dog accuracy: %f%%" % (dog_results))
print("condor accuracy: %f%%" % (eagle_results))
print("dolphin accuracy: %f%%" % (dolphin_results))
print("dragon accuracy: %f%%" % (dragon_results))

# 输出结果如下:
# Dog accuracy: 0.000000%
# condor accuracy: 0.000000%
# dolphin accuracy: 0.000000%
# dragon accuracy: 50.000000%

 

 

4 用人工神精网络进行手写数字识别

手写数字数据库,下载地址

http://yann.lecun.com/exdb/mnist

 

迷你库

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Time   : 2016/12/17 10:44

# @Author : Retacn

# @Site   : opencv ann 手写数字识别

# @File   : digits_ann.py

# @Software: PyCharm

__author__ = "retacn"

__copyright__ = "property ofmankind."

__license__ = "CN"

__version__ = "0.0.1"

__maintainer__ = "retacn"

__email__ = "zhenhuayue@sina.com"

__status__ = "Development"

 

import cv2

import pickle

import numpy as np

import gzip

 

 

def load_data():

   mnist = gzip.open('./data/mnist.pkl.gz', 'rb')

   training_data, classification_data, test_data = pickle.load(mnist,encoding='latin1')

   mnist.close()

   return (training_data, classification_data, test_data)

 

 

def wrap_data():

   tr_d, va_d, te_d = load_data()

   training_inputs = [np.reshape(x, (784, 1)) for x in tr_d[0]]

   training_results = [vectorized_result(y) for y in tr_d[1]]

   training_data = zip(training_inputs, training_results)

   validation_inputs = [np.reshape(x, (784, 1)) for x in va_d[0]]

    validation_data = zip(validation_inputs,va_d[1])

   test_inputs = [np.reshape(x, (784, 1)) for x in te_d[0]]

   test_data = zip(test_inputs, te_d[1])

   return (training_data, validation_data, test_data)

 

 

# 给出类标签,创建10个元素的0数组

# 参数j表示要置1的位置

def vectorized_result(j):

    e= np.zeros((10, 1))

   e[j] = 1.0

   return e

 

 

# 创建ann

def create_ANN(hidden=20):

   ann = cv2.ml.ANN_MLP_create()

    #设置各层大小

   ann.setLayerSizes(np.array([784, hidden, 10]))

    #采用反向传播方式

   ann.setTrainMethod(cv2.ml.ANN_MLP_RPROP)

   ann.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM)

    #指定ann的终止条件

   ann.setTermCriteria((cv2.TERM_CRITERIA_EPS | cv2.TermCriteria_COUNT, 20,1))

   return ann

 

 

# 训练函数

def train(ann, samples=10000, epochs=1):

   tr, val, test = wrap_data()

   for x in range(epochs):

       counter = 0

       for img in tr:

           if (counter > samples):

                break

           if (counter % 1000 == 0):

                print("Epoch %d: Trained%d/%d " % (x, counter, samples))

           counter += 1

           data, digit = img

           # ravel()将多维数组拉平为一维

           ann.train(np.array([data.ravel()], dtype=np.float32),

                      cv2.ml.ROW_SAMPLE,

                      np.array([digit.ravel()],dtype=np.float32))

       print('Epoch %d complete' % x)

   return ann, test

 

 

# 检查神精网络工作

def test(ann, test_data):

   sample = np.array(test_data[0][0].ravel(), dtype=np.float32).reshape(28,28)

   cv2.imshow("sample", sample)

   cv2.waitKey()

   print(ann.predict(np.array([test_data[0][0].ravel()],dtype=np.float32)))

 

 

def predict(ann, sample):

   resized = sample.copy()

   rows, cols = resized.shape

   if (rows != 28 or cols != 28) and rows * cols > 0:

       resized = cv2.resize(resized, (28, 28), interpolation=cv2.INTER_CUBIC)

   return ann.predict(np.array([resized.ravel()], dtype=np.float32))

 

 

if __name__ == "__main__":

   pass

# print(vectorized_result(2))

 

 

 

 

 

 

 

 

 

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Time   : 2016/12/17 11:35

# @Author : Retacn

# @Site   : 识别手写数字图像

# @File   : digits_image.py

# @Software: PyCharm

__author__ = "retacn"

__copyright__ = "property ofmankind."

__license__ = "CN"

__version__ = "0.0.1"

__maintainer__ = "retacn"

__email__ = "zhenhuayue@sina.com"

__status__ = "Development"

 

import cv2

import numpy as np

import Nine.digits_ann as ANN

 

 

# 确定矩形是否完全包含在另一个中

def inside(r1, r2):

   x1, y1, w1, h1 = r1

   x2, y2, w2, h2 = r2

   if (x1 > x2) and (y1 > y2) and (x1 + w1 < x2 + w2) and (y1 + h1< y2 + h2):

       return True

   else:

       return False

 

 

# 取得数字周围矩形,将其转换为正方形

def wrap_digit(rect):

   x, y, w, h = rect

   padding = 5

   hcenter = x + w / 2

   vcenter = y + h / 2

   if (h > w):

       w = h

       x = hcenter - (w / 2)

   else:

       h = w

       y = vcenter - (h / 2)

   return (int(x - padding), int(y - padding), int(w + padding), int(h +padding))

 

 

# 创建神经网络,中间层为58,训练50000个样本

ann, test_data =ANN.train(ANN.create_ANN(100), 50000,30)

font = cv2.FONT_HERSHEY_SIMPLEX

 

# 读入图像

PATH = './image/numbers.jpg'

# PATH = './image/MNISTsamples.png'

img = cv2.imread(PATH,cv2.IMREAD_UNCHANGED)

# 更换颜色空间

bw = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 高斯模糊

bw = cv2.GaussianBlur(bw, (7, 7), 0)

# 设置阈值

ret, thbw = cv2.threshold(bw, 127, 255,cv2.THRESH_BINARY_INV)

# 腐蚀

thbw = cv2.erode(thbw, np.ones((2, 2),np.uint8), iterations=2)

# 查找轮廓

image, cntrs, hier =cv2.findContours(thbw.copy(),  # 源图像

                                     cv2.RETR_TREE,  # 模式为查询所有

                                     cv2.CHAIN_APPROX_SIMPLE)  # 查询方法

 

rectangles = []

for c in cntrs:

    r= x, y, w, h = cv2.boundingRect(c)

    a= cv2.contourArea(c)

    b= (img.shape[0] - 3) * (img.shape[1] - 3)

 

   is_inside = False

   for q in rectangles:

       if inside(r, q):

           is_inside = True

           break

   if not is_inside:

       if not a == b:

           rectangles.append(r)

# 向预测函数伟递正方形区域

for r in rectangles:

   x, y, w, h = wrap_digit(r)

    #绘制矩形

    cv2.rectangle(img, (x, y), (x + w, y + h), (0,255, 0), 2)

    #取得部分图像

   roi = thbw[y:y + h, x:x + w]

 

   try:

       digit_class = int(ANN.predict(ann, roi.copy())[0])

   except:

       continue

   cv2.putText(img, '%d' % digit_class, (x, y - 1), font, 1, (0, 255, 0))

 

cv2.imshow("thbw", thbw)

cv2.imshow("contours", img)

cv2.imwrite('./image/sample.jpg', img)

cv2.waitKey()

 

posted @ 2016-12-18 12:37  retacn_yue  阅读(431)  评论(0编辑  收藏  举报