深度学习实验手册

深度学习实验手册

文章目录

  • 深度学习实验手册
    • 一、基础理论
      • 1. 自定义感知机
      • 2. 验证图像卷积运算效果
    • 二、OpenCV部分
      • 1. OpenCV安装
      • 2. OpenCV基本操作
        • 1)读取、图像、保存图像
      • 3. 图像色彩操作
        • 1)彩色图像转换为灰度图像
        • 2)色彩通道操作
        • 3)灰度直方图均衡化
        • 4)彩色亮度直方图均衡化
        • 5)色彩提取
        • 6)二值化与反二值化
      • 4. 图像形态操作
        • 1)图像翻转
        • 2)图像仿射变换
        • 3)图像缩放
        • 4)图像裁剪
        • 5)图像相加
        • 6)图像相减
        • 7)透视变换
        • 8)图像腐蚀
        • 9)图像膨胀
        • 10)图像开运算
        • 11)图像闭运算
        • 12)形态学梯度
      • 5. 图像梯度处理
        • 1)模糊处理
        • 2)图像锐化处理
        • 3)边沿检测
      • 6. 轮廓处理
        • 1)查找并绘制轮廓
        • 2)绘制矩形包围框
        • 3)绘制圆形包围圈
        • 4)绘制最佳拟合椭圆
        • 5)逼近多边形
      • 7. 视频基本处理
        • 1)读取摄像头
        • 2)播放视频文件
        • 3)捕获并保存视频
      • 8. 综合案例
        • 1)利用OpenCV实现图像校正
        • 2)利用OpenCV检测芯片瑕疵
    • 三、Tensorflow
      • 1. 查看Tensorflow版本
      • 2. Helloworld程序
      • 3. 张量相加
      • 4. 查看图对象
      • 5. 指定执行某个图
      • 6. 查看张量属性
      • 7. 生成张量
      • 8. 张量类型转换
      • 9. 占位符使用
      • 10. 改变张量形状
      • 11. 数学计算
      • 12. 变量使用示例
      • 13. 可视化
      • 14. 实现线性回归
      • 15. 模型保存与加载
      • 16. CSV样本读取
      • 18. 图像样本读取
      • 19. 实现手写体识别
      • 20. 利用CNN实现服饰识别

一、基础理论

1. 自定义感知机

# 00_percetron.py
# 实现感知机

# 实现逻辑和
def AND(x1, x2):
    w1, w2, theta = 0.5, 0.5, 0.7
    tmp = x1 * w1 + x2 * w2
    if tmp <= theta:
        return 0
    else:
        return 1

print(AND(1, 1))
print(AND(1, 0))


# 实现逻辑或
def OR(x1, x2):
    w1, w2, theta = 0.5, 0.5, 0.2
    tmp = x1 * w1 + x2 * w2
    if tmp <= theta:
        return 0
    else:
        return 1

print(OR(0, 1))
print(OR(0, 0))

# 实现异或
def XOR(x1, x2):
    s1 = not AND(x1, x2) # 与非门
    s2 = OR(x1, x2)
    y = AND(s1, s2)
    return y

print(XOR(1, 0))
print(XOR(0, 1))
print(XOR(1, 1))
print(XOR(0, 0))

2. 验证图像卷积运算效果

from scipy import signal
from scipy import misc
import matplotlib.pyplot as plt
import numpy as np
import scipy.ndimage as sn

im = misc.imread("data/zebra.png", flatten=True)
# face = sn.imread("data/zebra.png", flatten=True)
flt = np.array([[-1, 0, 1],
                [-2, 0, 2],
                [-1, 0, 1]])

flt2 = np.array([[1, 2, 1],
                 [0, 0, 0],
                 [-1, -2, -1]])

# 把图像的face数组和设计好的卷积和作二维卷积运算,设计边界处理方式为symm
conv_img1 = signal.convolve2d(im, flt,
                              boundary='symm',
                              mode='same').astype("int32")

conv_img2 = signal.convolve2d(im, flt2,
                              boundary='symm',
                              mode='same').astype("int32")

plt.figure("Conv2D")
plt.subplot(131)
plt.imshow(im, cmap='gray')  # 显示原始的图
plt.xticks([])
plt.yticks([])

plt.subplot(132)
plt.xticks([])
plt.yticks([])
plt.imshow(conv_img1, cmap='gray')  # 卷积后的图

plt.subplot(133)
plt.xticks([])
plt.yticks([])
plt.imshow(conv_img2, cmap='gray')  # 卷积后的图

plt.show()

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ScxHWF1-1632663143880)(img/img_conv.png)]

OpenCV版:

from scipy import misc
from scipy import signal
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import scipy.ndimage as sn
import cv2
import pylab

im = cv2.imread("../data/zebra.png",0)

flt = np.array([[-1,0,1],
                [-2,0,2],
                [-1,0,1]])/2
flt2 = np.array([[1,2,1],
                 [0,0,0],
                 [-1,-2,-1]])/2

conv_img1 = cv2.filter2D(im, -1, flt,borderType=1)
conv_img2 = cv2.filter2D(im, -1, flt2,borderType=1)

cv2.imshow("im",im)
cv2.imshow("conv_img1",conv_img1)
cv2.imshow("conv_img2",conv_img2)
cv2.waitKey()
cv2.destroyAllWindows()

二、OpenCV部分

1. OpenCV安装

执行以下命令安装opencv-python库(核心库)和opencv-contrib-python库(贡献库)。注意:命令拷贝后要合成一行执行,中间不要换行。

# 安装opencv核心库
pip3 install  --user opencv-python==3.4.2.16 --index-url https://pypi.tuna.tsinghua.edu.cn/simple/  --trusted-host https://pypi.tuna.tsinghua.edu.cn

# 安装opencv贡献库
pip3 install  --user opencv-contrib-python==3.4.2.16 --index-url https://pypi.tuna.tsinghua.edu.cn/simple/  --trusted-host https://pypi.tuna.tsinghua.edu.cn

2. OpenCV基本操作

1)读取、图像、保存图像

# 读取图像
import cv2

im = cv2.imread("../data/Linus.png", 1) # 1表示3通道彩色,0表示单通道灰度
cv2.imshow("test", im) # 在test窗口中显示图像

print(type(im))  # 打印数据类型
print(im.shape)  # 打印图像尺寸

cv2.imwrite("../data/Linus_2.png", im)  # 将图像保存到指定路径

cv2.waitKey()  # 等待用户按键反馈
cv2.destroyAllWindows()  # 销毁所有创建的窗口

执行结果:

深度学习实验手册_第1张图片

3. 图像色彩操作

1)彩色图像转换为灰度图像

# 彩色图像转换为灰度图像示例
import cv2

im = cv2.imread("../data/Linus.png", 1)
cv2.imshow("RGB", im) # 在test窗口中显示图像

# 使用cvtColor进行颜色空间变化,COLOR_BGR2GRAY表示BGR to GRAY
img_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) # 彩色图像灰度化
cv2.imshow("Gray", img_gray)

cv2.waitKey()  # 等待用户按键反馈
cv2.destroyAllWindows()  # 销毁所有创建的窗口

执行结果:

深度学习实验手册_第2张图片

2)色彩通道操作

# 色彩通道操作:通道表示为BGR
import numpy as np
import cv2

im = cv2.imread("../data/opencv2.png")
print(im.shape)
cv2.imshow("im", im)

# 取出蓝色通道,当做单通道图像显示
b = im[:, :, 0]
cv2.imshow("b", b)

# 去掉蓝色通道(索引为0的通道)
im[:, :, 0] = 0
cv2.imshow("im-b0", im)

# 去掉绿色通道(索引为1的通道)
im[:, :, 1] = 0
cv2.imshow("im-b0g0", im)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第3张图片

3)灰度直方图均衡化

# 直方图均衡化示例
import numpy as np
import cv2
from matplotlib import pyplot as plt

im = cv2.imread("../data/sunrise.jpg", 0)
cv2.imshow("orig", im)

# 直方图均衡化
im_equ = cv2.equalizeHist(im)
cv2.imshow("equ1", im_equ)

# 绘制灰度直方图
## 原始直方图
print(im.ravel())
plt.subplot(2, 1, 1)
plt.hist(im.ravel(), #ravel返回一个连续的扁平数组
         256, [0, 256], label="orig")
plt.legend()

## 均衡化处理后的直方图
plt.subplot(2, 1, 2)
plt.hist(im_equ.ravel(), 256, [0, 256], label="equalize")
plt.legend()

plt.show()

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第4张图片

4)彩色亮度直方图均衡化

# 彩色图像亮度直方图均衡化
import cv2

# 读取原始图片
original = cv2.imread('../data/sunrise.jpg')
cv2.imshow('Original', original)

# BRG空间转换为YUV空间
# YUV:亮度,色度,饱和度,其中Y通道为亮度通道
yuv = cv2.cvtColor(original, cv2.COLOR_BGR2YUV)
print("yuv.shape:", yuv.shape)

yuv[..., 0] = cv2.equalizeHist(yuv[..., 0])  # 取出亮度通道,均衡化并赋回原图像
equalized_color = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR)
cv2.imshow('Equalized Color', equalized_color)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第5张图片

5)色彩提取

从图片中提取特定颜色

import cv2
import numpy as np

im = cv2.imread("../data/opencv2.png")
hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
cv2.imshow('opencv', im)

# =============指定蓝色值的范围=============
# 蓝色H通道值为120,通常取120上下10的范围
# S通道和V通道通常取50~255间,饱和度太低、色调太暗计算出来的颜色不准确
minBlue = np.array([110, 50, 50])
maxBlue = np.array([130, 255, 255])
# 确定蓝色区域
mask = cv2.inRange(hsv, minBlue, maxBlue)  # 选取出掩模
# cv2.imshow("mask", mask)
# 通过掩码控制的按位与运算,锁定蓝色区域
blue = cv2.bitwise_and(im, im, mask=mask)  # 执行掩模运算
cv2.imshow('blue', blue)

# =============指定绿色值的范围=============
minGreen = np.array([50, 50, 50])
maxGreen = np.array([70, 255, 255])
# 确定绿色区域
mask = cv2.inRange(hsv, minGreen, maxGreen)
# cv2.imshow("mask", mask)
# 通过掩码控制的按位与运算,锁定绿色区域
green = cv2.bitwise_and(im, im, mask=mask)  # 执行掩模运算
cv2.imshow('green', green)

# =============指定红色值的范围=============
minRed = np.array([0, 50, 50])
maxRed = np.array([30, 255, 255])
# 确定红色区域
mask = cv2.inRange(hsv, minRed, maxRed)
# cv2.imshow("mask", mask)
# 通过掩码控制的按位与运算,锁定红色区域
red = cv2.bitwise_and(im, im, mask=mask)  # 执行掩模运算
cv2.imshow('red', red)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第6张图片

6)二值化与反二值化

# 二值化处理
import cv2 as cv

# 读取图像
img = cv.imread("../data/lena.jpg", 0)
cv.imshow("img", img)  # 显示原始图像

# 二值化
t, rst = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
cv.imshow("rst", rst)  # 显示二值化图像

# 反二值化
t, rst2 = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
cv.imshow("rst2", rst2)  # 显示反二值化图像

cv.waitKey()
cv.destroyAllWindows()

执行结果:

深度学习实验手册_第7张图片

4. 图像形态操作

1)图像翻转

# 图像翻转示例
import numpy as np
import cv2

im = cv2.imread("../data/Linus.png")
cv2.imshow("src", im)

# 0-垂直镜像
im_flip0 = cv2.flip(im, 0)
cv2.imshow("im_flip0", im_flip0)

# 1-水平镜像
im_flip1 = cv2.flip(im, 1)
cv2.imshow("im_flip1", im_flip1)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第8张图片

2)图像仿射变换

# 图像仿射变换
import numpy as np
import cv2

def translate(img, x, y):
    """
    坐标平移变换
    :param img: 原始图像数据
    :param x:平移的x坐标
    :param y:平移的y坐标
    :return:返回平移后的图像
    """
    h, w = img.shape[:2]  # 获取图像高、宽

    # 定义平移矩阵
    M = np.float32([[1, 0, x],
                    [0, 1, y]])
    # 使用openCV仿射操作实现平移变换
    shifted = cv2.warpAffine(img, M, (w, h))  # 第三个参数为输出图像尺寸

    return shifted  # 返回平移后的图像


def rotate(img, angle, center=None, scale=1.0):
    """
    图像旋转变换
    :param img: 原始图像数据
    :param angle: 旋转角度
    :param center: 旋转中心,如果为None则以原图中心为旋转中心
    :param scale: 缩放比例,默认为1
    :return: 返回旋转后的图像
    """
    h, w = img.shape[:2]  # 获取图像高、宽

    # 旋转中心默认为图像中心
    if center is None:
        center = (w / 2, h / 2)

    # 计算旋转矩阵
    M = cv2.getRotationMatrix2D(center, angle, scale)

    # 使用openCV仿射变换实现函数旋转
    rotated = cv2.warpAffine(img, M, (w, h))

    return rotated  # 返回旋转后的矩阵

if __name__ == "__main__":
    # 读取并显示原始图像
    im = cv2.imread("../data/Linus.png")
    cv2.imshow("SrcImg", im)

    # 图像向下移动50像素
    shifted = translate(im, 0, 50)
    cv2.imshow("Shifted1", shifted)

    # 图像向左移动40, 下移动40像素
    shifted = translate(im, -40, 40)
    cv2.imshow("Shifted2", shifted)

    # 逆时针旋转45度
    rotated = rotate(im, 45)
    cv2.imshow("rotated1", rotated)

    # 顺时针旋转180度
    rotated = rotate(im, -90)
    cv2.imshow("rorated2", rotated)

    cv2.waitKey()
    cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第9张图片

3)图像缩放

# 图像缩放示例
import numpy as np
import cv2

im = cv2.imread("../data/Linus.png")
cv2.imshow("src", im)

h, w = im.shape[:2]  # 获取图像尺寸


dst_size = (int(w/2), int(h/2))  # 缩放目标尺寸,宽高均为原来1/2
resized = cv2.resize(im, dst_size)  # 执行缩放
cv2.imshow("reduce", resized)

dst_size = (200, 300)  # 缩放目标尺寸,宽200,高300
method = cv2.INTER_NEAREST  # 最邻近插值
resized = cv2.resize(im, dst_size, interpolation=method)  # 执行缩放
cv2.imshow("NEAREST", resized)

dst_size = (200, 300)  # 缩放目标尺寸,宽200,高300
method = cv2.INTER_LINEAR  # 双线性插值
resized = cv2.resize(im, dst_size, interpolation=method)  # 执行缩放
cv2.imshow("LINEAR", resized)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第10张图片

4)图像裁剪

import numpy as np
import cv2


# 图像随机裁剪
def random_crop(im, w, h):
    start_x = np.random.randint(0, im.shape[1])  # 裁剪起始x像素
    start_y = np.random.randint(0, im.shape[0])  # 裁剪起始y像素

    new_img = im[start_y:start_y + h, start_x: start_x + w]  # 执行裁剪

    return new_img


# 图像中心裁剪
def center_crop(im, w, h):
    start_x = int(im.shape[1] / 2) - int(w / 2)  # 裁剪起始x像素
    start_y = int(im.shape[0] / 2) - int(h / 2)  # 裁剪起始y像素

    new_img = im[start_y:start_y + h, start_x: start_x + w]  # 执行裁剪

    return new_img


im = cv2.imread("../data/banana_1.png", 1)

new_img = random_crop(im, 200, 200)  # 随机裁剪
new_img2 = center_crop(im, 200, 200)  # 中心裁剪

cv2.imshow("orig", im)
cv2.imshow("random_crop", new_img)
cv2.imshow("center_crop", new_img2)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第11张图片

5)图像相加

# 图像相加示例
import cv2

a = cv2.imread("../data/lena.jpg", 0)
b = cv2.imread("../data/lily_square.png", 0)

dst1 = cv2.add(a, b)  # 图像直接相加,会导致图像过亮、过白

# 加权求和:addWeighted
# 图像进行加权和计算时,要求src1和src2必须大小、类型相同
dst2 = cv2.addWeighted(a, 0.6, b, 0.4, 0)  # 最后一个参数为亮度调节量

cv2.imshow("a", a)
cv2.imshow("b", b)
cv2.imshow("dst1", dst1)
cv2.imshow("dst2", dst2)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第12张图片

6)图像相减

# 图像相减运算示例
import cv2

a = cv2.imread("../data/3.png", 0)
b = cv2.imread("../data/4.png", 0)

dst = cv2.subtract(a, b)  # 两幅图像相减,是求出图像的差异

cv2.imshow("a", a)
cv2.imshow("b", b)
cv2.imshow("dst1", dst)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第13张图片

7)透视变换

# 透视变换
import cv2
import numpy as np

img = cv2.imread('../data/pers.png')
rows, cols = img.shape[:2]
print(rows, cols)

pts1 = np.float32([[58, 2], [167, 9], [8, 196], [126, 196]])# 输入图像四个顶点坐标
pts2 = np.float32([[16, 2], [167, 8], [8, 196], [169, 196]])# 输出图像四个顶点坐标

# 生成透视变换矩阵
M = cv2.getPerspectiveTransform(pts1, # 输入图像四个顶点坐标
                                pts2) # 输出图像四个顶点坐标
print(M.shape)
# 执行透视变换,返回变换后的图像
dst = cv2.warpPerspective(img, # 原始图像
                          M, # 3*3的变换矩阵
                          (cols, rows)) # 输出图像大小


# 生成透视变换矩阵
M = cv2.getPerspectiveTransform(pts2, # 输入图像四个顶点坐标
                                pts1) # 输出图像四个顶点坐标
# 执行透视变换,返回变换后的图像
dst2 = cv2.warpPerspective(dst, # 原始图像
                          M, # 3*3的变换矩阵
                          (cols, rows)) # 输出图像大小
cv2.imshow("img", img)
cv2.imshow("dst", dst)
cv2.imshow("dst2", dst2)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第14张图片

8)图像腐蚀

# 图像腐蚀
import cv2
import numpy as np

# 读取原始图像
im = cv2.imread("../data/5.png")
cv2.imshow("im", im)

# 腐蚀
kernel = np.ones((3, 3), np.uint8) # 用于腐蚀计算的核
erosion = cv2.erode(im, # 原始图像
                    kernel,  # 腐蚀核
                    iterations=3) # 迭代次数
cv2.imshow("erosion", erosion)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第15张图片

9)图像膨胀

# 图像膨胀
import cv2
import numpy as np

# 读取原始图像
im = cv2.imread("../data/6.png")
cv2.imshow("im", im)

# 膨胀
kernel = np.ones((3, 3), np.uint8)  # 用于膨胀计算的核
dilation = cv2.dilate(im,  # 原始图像
                      kernel,  # 膨胀核
                      iterations=5)  # 迭代次数
cv2.imshow("dilation", dilation)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第16张图片

10)图像开运算

# 开运算示例
import cv2
import numpy as np

# 读取原始图像
im1 = cv2.imread("../data/7.png")
im2 = cv2.imread("../data/8.png")

# 执行开运算
k = np.ones((10, 10), np.uint8)
r1 = cv2.morphologyEx(im1, cv2.MORPH_OPEN, k)
r2 = cv2.morphologyEx(im2, cv2.MORPH_OPEN, k)

cv2.imshow("im1", im1)
cv2.imshow("result1", r1)

cv2.imshow("im2", im2)
cv2.imshow("result2", r2)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hmAXQKoK-1632663143911)(img/开运算.png)]

11)图像闭运算

# 闭运算示例
import cv2
import numpy as np

# 读取图像
im1 = cv2.imread("../data/9.png")
im2 = cv2.imread("../data/10.png")

# 闭运算
k = np.ones((8, 8), np.uint8)
r1 = cv2.morphologyEx(im1, cv2.MORPH_CLOSE, k, iterations=2)
r2 = cv2.morphologyEx(im2, cv2.MORPH_CLOSE, k, iterations=2)

cv2.imshow("im1", im1)
cv2.imshow("result1", r1)
cv2.imshow("im2", im2)
cv2.imshow("result2", r2)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第17张图片

12)形态学梯度

# 形态学梯度示例
import cv2
import numpy as np

o = cv2.imread("../data/6.png")

k = np.ones((3, 3), np.uint8)
r = cv2.morphologyEx(o, cv2.MORPH_GRADIENT, k)

cv2.imshow("original", o)
cv2.imshow("result", r)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第18张图片

5. 图像梯度处理

1)模糊处理

# 图像模糊处理示例
import cv2
import numpy as np

## 中值滤波
im = cv2.imread("../data/lena.jpg", 0)
cv2.imshow("orig", im)

# 调用medianBlur中值模糊
# 第二个参数为滤波模板的尺寸大小,必须是大于1的奇数,如3、5、7
im_median_blur = cv2.medianBlur(im, 5)
cv2.imshow('median_blur', im_median_blur)

# 均值滤波
# 第二个参数为滤波模板的尺寸大小
im_mean_blur = cv2.blur(im, (3, 3))
cv2.imshow("mean_blur", im_mean_blur)

# 高斯滤波
# 第三个参数为高斯核在X方向的标准差
im_gaussian_blur = cv2.GaussianBlur(im, (5, 5), 3)
cv2.imshow("gaussian_blur", im_gaussian_blur)

# 使用高斯算子和filter2D自定义滤波操作
gaussan_blur = np.array([
    [1, 4, 7, 4, 1],
    [4, 16, 26, 16, 4],
    [7, 26, 41, 26, 7],
    [4, 16, 26, 16, 4],
    [1, 4, 7, 4, 1]], np.float32) / 273
# 使用filter2D, 第二个参数为目标图像的所需深度, -1表示和原图像相同
im_gaussian_blur2 = cv2.filter2D(im, -1, gaussan_blur)  
cv2.imshow("gaussian_blur2", im_gaussian_blur2)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第19张图片

2)图像锐化处理

# 图像锐化示例
import cv2
import numpy as np

im = cv2.imread("../data/lena.jpg", 0)
cv2.imshow("orig", im)

# 锐化算子1
sharpen_1 = np.array([[-1, -1, -1],
                      [-1, 9, -1],
                      [-1, -1, -1]])
# 使用filter2D进行滤波操作
im_sharpen1 = cv2.filter2D(im, -1, sharpen_1)
cv2.imshow("sharpen_1", im_sharpen1)

# 锐化算子2
sharpen_2 = np.array([[0, -1, 0],
                      [-1, 8, -1],
                      [0, 1, 0]]) / 4.0
# 使用filter2D进行滤波操作
im_sharpen2 = cv2.filter2D(im, -1, sharpen_2)
cv2.imshow("sharpen_2", im_sharpen2)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第20张图片

3)边沿检测

# 边沿检测示例
import cv2 as cv

im = cv.imread('../data/lily.png', 0)
cv.imshow('Original', im)

# # 水平方向滤波
# hsobel = cv.Sobel(im, cv.CV_64F, 1, 0, ksize=5)
# cv.imshow('H-Sobel', hsobel)
# # 垂直方向滤波
# vsobel = cv.Sobel(im, cv.CV_64F, 0, 1, ksize=5)
# cv.imshow('V-Sobel', vsobel)
# 两个方向滤波
sobel = cv.Sobel(im, cv.CV_64F, 1, 1, ksize=5)
cv.imshow('Sobel', sobel)

# Laplacian滤波:对细节反映更明显
laplacian = cv.Laplacian(im, cv.CV_64F)
cv.imshow('Laplacian', laplacian)

# Canny边沿提取
canny = cv.Canny(im,
                 50, # 滞后阈值
                 240) # 模糊度
cv.imshow('Canny', canny)

cv.waitKey()
cv.destroyAllWindows()

执行结果:

深度学习实验手册_第21张图片

6. 轮廓处理

边缘检测虽然能够检测出边缘,但边缘是不连续的,检测到的边缘并不是一个整体。图像轮廓是指将边缘连接起来形成的一个整体,用于后续的计算。

OpenCV提供了查找图像轮廓的函数cv2.findContours(),该函数能够查找图像内的轮廓信息,而函数cv2.drawContours()能够将轮廓绘制出来。图像轮廓是图像中非常重要的一个特征信息,通过对图像轮廓的操作,我们能够获取目标图像的大小、位置、方向等信息。一个轮廓对应着一系列的点,这些点以某种方式表示图像中的一条曲线。

1)查找并绘制轮廓

  • 查找轮廓函数:cv2.findContours

    • 语法格式:image,contours,hierarchy=cv2.findContours(image,mode,method)

    • 返回值

      • image:与函数参数中的原始图像image一致
      • contours:返回的轮廓。该返回值返回的是一组轮廓信息,每个轮廓都是由若干个点所构成的(每个轮廓为一个list表示)。例如,contours[i]是第i个轮廓(下标从0开始),contours[i][j]是第i个轮廓内的第j个点
      • hierarchy:图像的拓扑信息(反映轮廓层次)。图像内的轮廓可能位于不同的位置。比如,一个轮廓在另一个轮廓的内部。在这种情况下,我们将外部的轮廓称为父轮廓,内部的轮廓称为子轮廓。按照上述关系分类,一幅图像中所有轮廓之间就建立了父子关系。每个轮廓contours[i]对应4个元素来说明当前轮廓的层次关系。其形式为:[Next,Previous,First_Child,Parent],分别表示后一个轮廓的索引编号、前一个轮廓的索引编号、第1个子轮廓的索引编号、父轮廓的索引编号
    • 参数

      • image:原始图像。灰度图像会被自动处理为二值图像。在实际操作时,可以根据需要,预先使用阈值处理等函数将待查找轮廓的图像处理为二值图像。
      • mode:轮廓检索模式,有以下取值和含义:
      取值 含义
      cv2.RETR_EXTERNAL 只检测外轮廓
      cv2.RETR_LIST 对检测到的轮廓不建立等级关系
      cv2.RETR_CCOMP 检索所有轮廓并将它们组织成两级层次结构,上面的一层为外边界,下面的一层为内孔的边界
      cv2.RETR_TREE 建立一个等级树结构的轮廓
      • method:轮廓的近似方法,主要有如下取值:
      取值 含义
      cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))=1
      cv2.CHAIN_APPROX_SIMPLE 压缩水平方向、垂直方向、对角线方向的元素,只保留该方向的终点坐标
      cv2.CHAIN_APPROX_TC89_L1 使用teh-Chinl chain近似算法的一种风格
      cv2.CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain近似算法的一种风格
    • 注意事项

      • 待处理的源图像必须是灰度二值图
      • 都是从黑色背景中查找白色对象。因此,对象必须是白色的,背景必须是黑色的
      • 在OpenCV 4.x中,函数cv2.findContours()仅有两个返回值
  • 绘制轮廓:drawContours函数

    • 语法格式:image=cv2.drawContours(image, contours,contourIdx, color)
    • 参数
      • image:待绘制轮廓的图像
      • contours:需要绘制的轮廓,该参数的类型与函数 cv2.findContours()的输出 contours 相同,都是list类型
      • contourIdx:需要绘制的边缘索引,告诉函数cv2.drawContours()要绘制某一条轮廓还是全部轮廓。如果该参数是一个整数或者为零,则表示绘制对应索引号的轮廓;如果该值为负数(通常为“-1”),则表示绘制全部轮廓。
      • color:绘制的颜色,用BGR格式表示
# 查找图像轮廓
import cv2
import numpy as np

im = cv2.imread("../data/3.png")
cv2.imshow("orig", im)

gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

# 图像二值化处理,将大于阈值的设置为最大值,其它设置为0
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 查找图像边沿:cv2.findContours
img, contours, hierarchy = cv2.findContours(binary,  # 二值化处理后的图像
                                            cv2.RETR_EXTERNAL,  # 只检测外轮廓
                                            cv2.CHAIN_APPROX_NONE)  # 存储所有的轮廓点
# 打印所有轮廓值
arr_cnt = np.array(contours)
print(arr_cnt[0].shape)
print(arr_cnt[1].shape)
print(arr_cnt[2].shape)
print(arr_cnt[3].shape)
# print(arr_cnt[0])

# 绘制边沿
im_cnt = cv2.drawContours(im,  # 绘制图像
                          contours,  # 轮廓点列表
                          -1,  # 绘制全部轮廓
                          (0, 0, 255),  # 轮廓颜色:红色
                          2)  # 轮廓粗细
cv2.imshow("im_cnt", im_cnt)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第22张图片

2)绘制矩形包围框

函数cv2.boundingRect()能够绘制轮廓的矩形边界。该函数的语法格式为:

retval = cv2.boundingRect(array)  # 格式一
x,y,w,h = cv2.boundingRect(array) # 格式二
"""
参数:
	array:是灰度图像或轮廓
返回值:
	retval:表示返回的矩形边界的左上角顶点的坐标值及矩形边界的宽度和高度
	x, y, w, h: 矩形边界左上角顶点的x坐标、y坐标、宽度、高度
"""

代码:

# 绘制图像矩形轮廓
import cv2
import numpy as np

im = cv2.imread("../data/cloud.png", 0)
cv2.imshow("orig", im)

# 提取图像轮廓
ret, binary = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
img, contours, hierarchy = cv2.findContours(binary,
                                            cv2.RETR_LIST,  # 不建立等级关系
                                            cv2.CHAIN_APPROX_NONE)  # 存储所有的轮廓点
print("contours[0].shape:", contours[0].shape)

# 返回轮廓定点及边长
x, y, w, h = cv2.boundingRect(contours[0])  # 计算矩形包围框的x,y,w,h
print("x:", x, "y:", y, "w:", w, "h:", h)

# 绘制矩形包围框
brcnt = np.array([[[x, y]], [[x + w, y]], [[x + w, y + h]], [[x, y + h]]])
cv2.drawContours(im,  # 绘制图像
                 [brcnt],  # 轮廓点列表
                 -1,  # 绘制全部轮廓
                 (255, 255, 255),  # 轮廓颜色:白色
                 2)  # 轮廓粗细

cv2.imshow("result", im)  # 显示绘制后的图像

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第23张图片

3)绘制圆形包围圈

函数 cv2.minEnclosingCircle()通过迭代算法构造一个对象的面积最小包围圆形。该函数的语法格式为:

center,radius=cv2.minEnclosingCircle(points)
"""
参数:
	points: 轮廓数组
返回值:
	center: 最小包围圆形的中心
	radius: 最小包围圆形的半径
"""

代码:

# 绘制最小圆形
import cv2
import numpy as np

im = cv2.imread("../data/cloud.png", 0)
cv2.imshow("orig", im)

# 提取图像轮廓
ret, binary = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
img, contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

(x, y), radius = cv2.minEnclosingCircle(contours[0])
center = (int(x), int(y))
radius = int(radius)
cv2.circle(im, center, radius, (255, 255, 255), 2)  # 绘制圆

cv2.imshow("result", im)  # 显示绘制后的图像

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第24张图片

4)绘制最佳拟合椭圆

函数cv2.fitEllipse()可以用来构造最优拟合椭圆。该函数的语法格式是:

retval=cv2.fitEllipse(points)
"""
参数:
	points: 轮廓
返回值:
	retval: 为RotatedRect类型的值,包含外接矩形的质心、宽、高、旋转角度等参数信息,这些信息正好与椭圆的中心点、轴长度、旋转角度等信息吻合
"""

代码:

# 绘制最优拟合椭圆
import cv2
import numpy as np

im = cv2.imread("../data/cloud.png")
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
cv2.imshow("orig", gray)

# 提取图像轮廓
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
img, contours, hierarchy = cv2.findContours(binary,
                                            cv2.RETR_LIST,
                                            cv2.CHAIN_APPROX_NONE)

ellipse = cv2.fitEllipse(contours[0])  # 拟合最优椭圆
print("ellipse:", ellipse)
cv2.ellipse(im, ellipse, (0, 0, 255), 2)  # 绘制椭圆

cv2.imshow("result", im)  # 显示绘制后的图像

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第25张图片

5)逼近多边形

函数cv2.approxPolyDP()用来构造指定精度的逼近多边形曲线。该函数的语法格式为:

approxCurve = cv2.approxPolyDP(curve,epsilon,closed)
"""
参数:
	curve: 轮廓
	epsilon: 精度,原始轮廓的边界点与逼近多边形边界之间的最大距离
	closed: 布尔类型,该值为True时,逼近多边形是封闭的;否则,逼近多边形是不封闭的
返回值:
	approxCurve: 逼近多边形的点集
"""

代码:

# 构建多边形,逼近轮廓
import cv2
import numpy as np

im = cv2.imread("../data/cloud.png")
cv2.imshow("im", im)
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

# 提取图像轮廓
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
img, contours, hierarchy = cv2.findContours(binary,
                                            cv2.RETR_LIST,
                                            cv2.CHAIN_APPROX_NONE)
# 精度一
adp = im.copy()
epsilon = 0.005 * cv2.arcLength(contours[0], True)  # 精度,根据周长计算
approx = cv2.approxPolyDP(contours[0], epsilon, True)  # 构造多边形
adp = cv2.drawContours(adp, [approx], 0, (0, 0, 255), 2)  # 绘制多边形
cv2.imshow("result_0.005", adp)
# 精度二
adp2 = im.copy()
epsilon = 0.01 * cv2.arcLength(contours[0], True)  # 精度,根据周长计算
approx = cv2.approxPolyDP(contours[0], epsilon, True)  # 构造多边形
adp = cv2.drawContours(adp2, [approx], 0, (0, 0, 255), 2)  # 绘制多边形
cv2.imshow("result_0.01", adp2)

cv2.waitKey()
cv2.destroyAllWindows()

执行结果:

深度学习实验手册_第26张图片

7. 视频基本处理

1)读取摄像头

import numpy as npimport cv2cap = cv2.VideoCapture(0)  # 实例化VideoCapture对象, 0表示第一个摄像头while cap.isOpened():    ret, frame = cap.read()  # 捕获帧    cv2.imshow("frame", frame)    c = cv2.waitKey(1)  # 等待1毫秒,等待用户输入    if c == 27:  # ESC键        breakcap.release()  # 释放摄像头cv2.destroyAllWindows()

2)播放视频文件

import numpy as npimport cv2cap = cv2.VideoCapture("D:\\tmp\\min_nong.mp4")  # 打开视频文件while cap.isOpened():    ret, frame = cap.read()  # 读取帧    cv2.imshow("frame", frame)  # 显示    c = cv2.waitKey(25)    if c == 27:  # ESC键        breakcap.release()  # 释放视频设备cv2.destroyAllWindows()

3)捕获并保存视频

import numpy as np
import cv2

""" 编解码4字标记值说明
cv2.VideoWriter_fourcc('I','4','2','0')表示未压缩的YUV颜色编码格式,色度子采样为4:2:0。
    该编码格式具有较好的兼容性,但产生的文件较大,文件扩展名为.avi。
cv2.VideoWriter_fourcc('P','I','M','I')表示 MPEG-1编码类型,生成的文件的扩展名为.avi。
cv2.VideoWriter_fourcc('X','V','I','D')表示MPEG-4编码类型。如果希望得到的视频大小为平均值,可以选用这个参数组合。
    该组合生成的文件的扩展名为.avi。
cv2.VideoWriter_fourcc('T','H','E','O')表示Ogg Vorbis编码类型,文件的扩展名为.ogv。
cv2.VideoWriter_fourcc('F','L','V','I')表示Flash视频,生成的文件的扩展名为.flv。
"""
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc("I", "4", "2", "0")  # 编解码4字标记值
out = cv2.VideoWriter("output.avi",  # 文件名
                      fourcc,  # 编解码类型
                      20,  # fps(帧速度)
                      (640, 480))  # 视频分辨率

while cap.isOpened():
    ret, frame = cap.read()  # 读取帧
    if ret == True:
        out.write(frame)  # 写入帧
        cv2.imshow("frame", frame)
        if cv2.waitKey(1) == 27:  # ESC键
            break
    else:
        break

cap.release()
out.release()
cv2.destroyAllWindows()

8. 综合案例

1)利用OpenCV实现图像校正

【任务描述】

我们对图像中的目标进行分析和检测时,目标往往具有一定的倾斜角度,自然条件下拍摄的图像,完全平正是很少的。因此,需要将倾斜的目标“扶正”的过程就就叫做图像矫正。该案例中使用的原始图像如下:

深度学习实验手册_第27张图片

【代码】

# 图像校正示例
import cv2
import numpy as np

im = cv2.imread("../data/paper.jpg")
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
cv2.imshow('im', im)

# 模糊
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 膨胀
dilate = cv2.dilate(blurred,
                    cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))) # 根据函数返回kernel
# 检测边沿
edged = cv2.Canny(dilate,  # 原始图像
                  30, 120,  # 滞后阈值、模糊度
                  3)  # 孔径大小
# cv2.imshow("edged", edged)

# 轮廓检测
cnts = cv2.findContours(edged.copy(),
                        cv2.RETR_EXTERNAL,  # 只检测外轮廓
                        cv2.CHAIN_APPROX_SIMPLE)  # 只保留该方向的终点坐标
cnts = cnts[1]
docCnt = None

# 绘制轮廓
im_cnt = cv2.drawContours(im,  # 绘制图像
                          cnts,  # 轮廓点列表
                          -1,  # 绘制全部轮廓
                          (0, 0, 255),  # 轮廓颜色:红色
                          2)  # 轮廓粗细
cv2.imshow("im_cnt", im_cnt)

# 计算轮廓面积,并排序
if len(cnts) > 0:
    cnts = sorted(cnts,  # 数据
                  key=cv2.contourArea,  # 排序依据,根据contourArea函数结果排序
                  reverse=True)
    for c in cnts:
        peri = cv2.arcLength(c, True)  # 计算轮廓周长
        approx = cv2.approxPolyDP(c, 0.02 * peri, True)  # 轮廓多边形拟合
        # 轮廓为4个点表示找到纸张
        if len(approx) == 4:
            docCnt = approx
            break

print(docCnt)

# 用圆圈标记处角点
points = []
for peak in docCnt:
    peak = peak[0]
    # 绘制圆
    cv2.circle(im,  # 绘制图像
               tuple(peak), 10,  # 圆心、半径
               (0, 0, 255), 2)  # 颜色、粗细
    points.append(peak)  # 添加到列表
print(points)
cv2.imshow("im_point", im)

# 校正
src = np.float32([points[0], points[1], points[2], points[3]])  # 原来逆时针方向四个点
dst = np.float32([[0, 0], [0, 488], [337, 488], [337, 0]])  # 对应变换后逆时针方向四个点
m = cv2.getPerspectiveTransform(src, dst)  # 生成透视变换矩阵
result = cv2.warpPerspective(gray.copy(), m, (337, 488))  # 透视变换
cv2.imshow("result", result)  # 显示透视变换结果

cv2.waitKey()
cv2.destroyAllWindows()

【执行结果】

深度学习实验手册_第28张图片

2)利用OpenCV检测芯片瑕疵

【任务描述】

利用图像技术,检测出芯片镀盘区域瑕疵。样本图像中,粉红色区域为镀盘区域,镀盘内部空洞为瑕疵区域,利用图像技术检测镀盘是否存在瑕疵,如果存在则将瑕疵区域标记出来。

深度学习实验手册_第29张图片

【代码】

import cv2
import numpy as np
import math

# 第一步:图像预处理
## 1. 转换成灰度图像,进行二值化处理
im_cpu = cv2.imread("../../data/CPU3.png")
im_gray = cv2.cvtColor(im_cpu, cv2.COLOR_BGR2GRAY)  # 转换成灰度图像

# 提取出度盘轮廓
ret, im_bin = cv2.threshold(im_gray, 162, 255, cv2.THRESH_BINARY)  # 图像二值化
cv2.imshow("im_cpu", im_cpu)
cv2.imshow("im_gray", im_gray)
cv2.imshow("im_bin", im_bin)

# 提取轮廓、绘制边沿
img, contours, hierarchy = cv2.findContours(im_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# 绘制前景对象轮廓
mask = np.zeros(im_bin.shape, np.uint8)
mask = cv2.drawContours(mask, contours, -1, (255, 0, 0), -1)  # 绘制实心轮廓
cv2.imshow("mask", mask)

# 前景实心轮廓图和二值化图相减
im_sub = cv2.subtract(mask, im_bin)
cv2.imshow("im_sub", im_sub)

# 图像闭运算,先膨胀后腐蚀,去除内部毛刺
k = np.ones((10, 10), np.uint8)
im_close = cv2.morphologyEx(im_sub, cv2.MORPH_CLOSE, k, iterations=3)
cv2.imshow("im_close", im_close)

# 提取、绘制轮廓、计算面积
img, contours, hierarchy = cv2.findContours(im_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

(x, y), radius = cv2.minEnclosingCircle(contours[1])
center = (int(x), int(y))
radius = int(radius)
print("center:", center, " radius:", radius)
cv2.circle(im_close, center, radius, (255, 0, 0), 2)  # 绘制圆
cv2.imshow("im_gaussian_blur2", im_close)

# 在原始图片上绘制瑕疵
cv2.circle(im_cpu, center, radius, (0, 0, 255), 2)  # 绘制圆
cv2.imshow("im_cpu2", im_cpu)

#计算面积
area = math.pi * radius * radius
print("area:", area)
if area > 12:
    print("度盘表面有缺陷")

cv2.waitKey()
cv2.destroyAllWindows()

【执行结果】

深度学习实验手册_第30张图片

三、Tensorflow

1. 查看Tensorflow版本

from __future__ import absolute_import, division, print_function, unicode_literals

# 导入TensorFlow和tf.keras
import tensorflow as tf
from tensorflow import keras

# 导入辅助库
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)

2. Helloworld程序

# tf的helloworld程序
import tensorflow as tf

hello = tf.constant('Hello, world!')  # 定义一个常量
sess = tf.Session()  # 创建一个session
print(sess.run(hello))  # 计算
sess.close()

3. 张量相加

# 常量加法运算示例
import tensorflow as tf
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'  # 调整警告级别

a = tf.constant(5.0)  # 定义常量a
b = tf.constant(1.0)  # 定义常量a
c = tf.add(a, b)
print("c:", c)

graph = tf.get_default_graph()  # 获取缺省图
print(graph)

with tf.Session() as sess:
    print(sess.run(c))  # 执行计算

4. 查看图对象

# 常量加法运算示例
import tensorflow as tf
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'  # 调整警告级别

a = tf.constant(5.0)  # 定义常量a
b = tf.constant(1.0)  # 定义常量a
c = tf.add(a, b)
print("c:", c)

graph = tf.get_default_graph()  # 获取缺省图
print(graph)

with tf.Session() as sess:
    print(sess.run(c))  # 执行计算
    print(a.graph)  # 通过tensor获取graph对象
    print(c.graph)  # 通过op获取graph对象
    print(sess.graph)  # 通过session获取graph对象

5. 指定执行某个图

# 创建多个图,指定图运行
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'  # 调整警告级别

a = tf.constant(5.0)  # 定义常量a
b = tf.constant(1.0)  # 定义常量a
c = tf.add(a, b)

graph = tf.get_default_graph()  # 获取缺省图
print(graph)

graph2 = tf.Graph()
print(graph2)
with graph2.as_default(): # 在指定图上创建op
    d = tf.constant(11.0)

with tf.Session(graph=graph2) as sess:
    print(sess.run(d))  # 执行计算
    # print(sess.run(c))  # 报错

6. 查看张量属性

# 创建多个图,指定图运行
import tensorflow as tf
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'  # 调整警告级别

# a = tf.constant(5.0)  # 定义常量a
# a = tf.constant([1,2,3])
a = tf.constant([[1,2,3],[4,5,6]])

with tf.Session() as sess:
    print(sess.run(a))  # 执行计算
    print("name:", a.name)
    print("dtype:", a.dtype)
    print("shape:", a.shape)
    print("op:", a.op)
    print("graph:", a.graph)

7. 生成张量

# 创建张量操作import tensorflow as tf# 生成值全为0的张量tensor_zeros = tf.zeros(shape=[2, 3], dtype="float32")# 生成值全为1的张量tensor_ones = tf.ones(shape=[2, 3], dtype="float32")# 创建正态分布张量tensor_nd = tf.random_normal(shape=[10],                             mean=1.7,                             stddev=0.2,                             dtype="float32")# 生成和输入张量形状一样的张量,值全为1tensor_zeros_like = tf.zeros_like(tensor_ones)with tf.Session() as sess:    print(tensor_zeros.eval())  # eval表示在session中计算该张量    print(tensor_ones.eval())    print(tensor_nd.eval())    print(tensor_zeros_like.eval())

8. 张量类型转换

# 张量类型转换import tensorflow as tftensor_ones = tf.ones(shape=[2, 3], dtype="int32")tensor_float = tf.constant([1.1, 2.2, 3.3])with tf.Session() as sess:    print(tf.cast(tensor_ones, tf.float32).eval())    # print(tf.cast(tensor_float, tf.string).eval()) #不支持浮点数到字符串直接转换

9. 占位符使用

# 占位符示例import tensorflow as tf# 不确定数据,先使用占位符占个位置plhd = tf.placeholder(tf.float32, [2, 3])  # 2行3列的tensorplhd2 = tf.placeholder(tf.float32, [None, 3])  # N行3列的tensorwith tf.Session() as sess:    d = [[1, 2, 3],         [4, 5, 6]]    print(sess.run(plhd, feed_dict={plhd: d}))    print("shape:", plhd.shape)    print("name:", plhd.name)    print("graph:", plhd.graph)    print("op:", plhd.op)    print(sess.run(plhd2, feed_dict={plhd2: d}))

10. 改变张量形状

# 改变张量形状示例(重点)import tensorflow as tfpld = tf.placeholder(tf.float32, [None, 3])print(pld)pld.set_shape([4, 3])print(pld)# pld.set_shape([3, 3]) #报错,静态形状一旦固定就不能再设置静态形状# 动态形状可以创建一个新的张量,改变时候一定要注意元素的数量要匹配new_pld = tf.reshape(pld, [3, 4])print(new_pld)# new_pld = tf.reshape(pld, [2, 4]) # 报错,元素的数量不匹配with tf.Session() as sess:    pass

11. 数学计算

# 数学计算示例
import tensorflow as tf

x = tf.constant([[1, 2], [3, 4]], dtype=tf.float32)
y = tf.constant([[4, 3], [3, 2]], dtype=tf.float32)

x_add_y = tf.add(x, y)  # 张量相加
x_mul_y = tf.matmul(x, y)  # 张量相乘
log_x = tf.log(x)  # log(x)

# reduce_sum: 此函数计算一个张量的各个维度上元素的总和
x_sum_1 = tf.reduce_sum(x, axis=[1]) #0-列方向 1-行方向

# segment_sum: 沿张量的片段计算总和
# 函数返回的是一个Tensor,它与data有相同的类型,与data具有相同的形状
# 但大小为 k(段的数目)的维度0除外
data = tf.constant([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=tf.float32)
segment_ids = tf.constant([0, 0, 0, 1, 1, 2, 2, 2, 2, 2], dtype=tf.int32)
x_seg_sum = tf.segment_sum(data, segment_ids)  # [6, 9, 40]

with tf.Session() as sess:
    print(x_add_y.eval())
    print(x_mul_y.eval())
    print(x_mul_y.eval())
    print(log_x.eval())
    print(x_sum_1.eval())
    print(x_seg_sum.eval())

12. 变量使用示例

# 变量OP示例
import tensorflow as tf
# 创建普通张量
a = tf.constant([1, 2, 3, 4, 5])
# 创建变量
var = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0),
                  name="variable")

# 变量必须显式初始化, 这里定义的是初始化操作,并没有运行
init_op = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init_op)
    print(sess.run([a, var]))

13. 可视化

第一步:编写代码

# 变量OP示例
import tensorflow as tf

''' 变量OP
1. 变量OP能够持久化保存,普通张量则不可
2. 当定义一个变量OP时,在会话中进行初始化
3. name参数:在tensorboard使用的时候显示名字,可以让相同的OP进行区分
'''

# 创建普通张量
a = tf.constant([1, 2, 3, 4, 5])
# 创建变量
var = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0),
                  name="variable")

b = tf.constant(3.0, name="a")
c = tf.constant(4.0, name="b")
d = tf.add(b, c, name="add")

# 变量必须显式初始化, 这里定义的是初始化操作,并没有运行
init_op = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init_op)
    # 将程序图结构写入事件文件
    fw = tf.summary.FileWriter("../summary/", graph=sess.graph)
    print(sess.run([a, var]))

第二步:启动tensorborad

tensorboard  --logdir="PycharmProjects/tensorflow_study/summary/"

第三步:访问tensorborad主页

http://127.0.0.1:6006

14. 实现线性回归

# 线性回归示例
import tensorflow as tf

# 第一步:创建数据
x = tf.random_normal([100, 1], mean=1.75, stddev=0.5, name="x_data")
y_true = tf.matmul(x, [[2.0]]) + 5.0  # 矩阵相乘必须是二维的

# 第二步:建立线性回归模型
# 建立模型时,随机建立权重、偏置 y = wx + b
# 权重需要不断更新,所以必须是变量类型. trainable指定该变量是否能随梯度下降一起变化
weight = tf.Variable(tf.random_normal([1, 1], name="w"),
                     trainable=True)  # 训练过程中值是否允许变化
bias = tf.Variable(0.0, name="b", trainable=True)  # 偏置
y_predict = tf.matmul(x, weight) + bias  # 计算 wx + b

# # 第三步:求损失函数,误差(均方差)
loss = tf.reduce_mean(tf.square(y_true - y_predict))

# # 第四步:使用梯度下降法优化损失
# 学习率是比价敏感的参数,过小会导致收敛慢,过大可能导致梯度爆炸
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

#### 收集损失值
tf.summary.scalar("losses", loss)
merged = tf.summary.merge_all() #将所有的摘要信息保存到磁盘

init_op = tf.global_variables_initializer()
with tf.Session() as sess:  # 通过Session运行op
    sess.run(init_op)
    # 打印初始权重、偏移值
    print("weight:", weight.eval(), " bias:", bias.eval())

    #### 指定事件文件
    fw = tf.summary.FileWriter("../summary/", graph=sess.graph)

    for i in range(500):  # 循环执行训练
        sess.run(train_op)  # 执行训练
        summary = sess.run(merged) #### 运行合并摘要op
        fw.add_summary(summary, i) #### 写入文件
        print(i, ":", i, "weight:", weight.eval(), " bias:", bias.eval())

15. 模型保存与加载

# 模型保存示例
import tensorflow as tf
import os

# 第一步:创建数据
x = tf.random_normal([100, 1], mean=1.75, stddev=0.5, name="x_data")
y_true = tf.matmul(x, [[2.0]]) + 5.0  # 矩阵相乘必须是二维的

# 第二步:建立线性回归模型
# 建立模型时,随机建立权重、偏置 y = wx + b
# 权重需要不断更新,所以必须是变量类型. trainable指定该变量是否能随梯度下降一起变化
weight = tf.Variable(tf.random_normal([1, 1], name="w"),
                     trainable=True)  # 训练过程中值是否允许变化
bias = tf.Variable(0.0, name="b", trainable=True)  # 偏置
y_predict = tf.matmul(x, weight) + bias  # 计算 wx + b

# # 第三步:求损失函数,误差(均方差)
loss = tf.reduce_mean(tf.square(y_true - y_predict))

# # 第四步:使用梯度下降法优化损失
# 学习率是比价敏感的参数,过小会导致收敛慢,过大可能导致梯度爆炸
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

# 收集损失值
tf.summary.scalar("losses", loss)
merged = tf.summary.merge_all() #将所有的摘要信息保存到磁盘

init_op = tf.global_variables_initializer()

saver = tf.train.Saver() #实例化Saver
with tf.Session() as sess:  # 通过Session运行op
    sess.run(init_op)
    print("weight:", weight.eval(), " bias:", bias.eval())     # 打印初始权重、偏移值
    fw = tf.summary.FileWriter("../summary/", graph=sess.graph) # 指定事件文件
    # 训练之前,加载之前训练的模型,覆盖之前的参数
    if os.path.exists("../model/linear_model/checkpoint"):
        saver.restore(sess, "../model/linear_model/")

    for i in range(500):  # 循环执行训练
        sess.run(train_op)  # 执行训练
        summary = sess.run(merged) # 运行合并后的tensor
        fw.add_summary(summary, i)
        print(i, ":", i, "weight:", weight.eval(), " bias:", bias.eval())

    saver.save(sess, "../model/linear_model/")

16. CSV样本读取

# csv文件读取示例
import tensorflow as tf
import os
def csv_read(filelist):
    # 2. 构建文件队列
    file_queue = tf.train.string_input_producer(filelist)
    # 3. 构建csv reader,读取队列内容(一行)
    reader = tf.TextLineReader()
    k, v = reader.read(file_queue)
    # 4. 对每行内容进行解码
    ## record_defaults:指定每一个样本每一列的类型,指定默认值
    records = [["None"], ["None"]]
    example, label = tf.decode_csv(v, record_defaults=records)  # 每行两个值
    # 5. 批处理
    # batch_size: 跟队列大小无关,只决定本批次取多少数据
    example_bat, label_bat = tf.train.batch([example, label],
                                            batch_size=9,
                                            num_threads=1,
                                            capacity=9)
    return example_bat, label_bat


if __name__ == "__main__":
    # 1. 找到文件,构造一个列表
    dir_name = "./test_data/"
    file_names = os.listdir(dir_name)
    file_list = []
    for f in file_names:
        file_list.append(os.path.join(dir_name, f))  # 拼接目录和文件名
        
    example, label = csv_read(file_list)
    # 开启session运行结果
    with tf.Session() as sess:
        coord = tf.train.Coordinator() # 定义线程协调器
        # 开启读取文件线程
        # 调用 tf.train.start_queue_runners 之后,才会真正把tensor推入内存序列中
        # 供计算单元调用,否则会由于内存序列为空,数据流图会处于一直等待状态
        # 返回一组线程
        threads = tf.train.start_queue_runners(sess, coord=coord)
        print(sess.run([example, label])) # 打印读取的内容
        # 回收线程
        coord.request_stop()
        coord.join(threads)

18. 图像样本读取

# 图片文件读取示例
import tensorflow as tf
import os

def img_read(filelist):
    # 1. 构建文件队列
    file_queue = tf.train.string_input_producer(filelist)
    # 2. 构建reader读取文件内容,默认读取一张图片
    reader = tf.WholeFileReader()
    k, v = reader.read(file_queue)

    # 3. 对图片数据进行解码
    img = tf.image.decode_jpeg(v)  

    # 4. 批处理, 图片需要处理成统一大小
    img_resized = tf.image.resize(img, [200, 200])  # 200*200
    img_resized.set_shape([200, 200, 3])  # 固定样本形状,批处理时对数据形状有要求
    img_bat = tf.train.batch([img_resized],
                             batch_size=10,
                             num_threads=1)
    return img_bat


if __name__ == "__main__":
    # 1. 找到文件,构造一个列表
    dir_name = "../data/test_img/"
    file_names = os.listdir(dir_name)
    file_list = []
    for f in file_names:
        file_list.append(os.path.join(dir_name, f))  # 拼接目录和文件名
    imgs = img_read(file_list)
    # 开启session运行结果
    with tf.Session() as sess:
        coord = tf.train.Coordinator()  # 定义线程协调器
        # 开启读取文件线程
        # 调用 tf.train.start_queue_runners 之后,才会真正把tensor推入内存序列中
        # 供计算单元调用,否则会由于内存序列为空,数据流图会处于一直等待状态
        # 返回一组线程
        threads = tf.train.start_queue_runners(sess, coord=coord)
        # print(sess.run([imgs]))  # 打印读取的内容
        imgs = imgs.eval()

        # 回收线程
        coord.request_stop()
        coord.join(threads)

## 显示图片
print(imgs.shape)
import matplotlib.pyplot as plt

plt.figure("Img Show", facecolor="lightgray")

for i in range(10):
    plt.subplot(2, 5, i+1)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(imgs[i].astype("int32"))

plt.tight_layout()
plt.show()

19. 实现手写体识别

# 手写体识别
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import pylab

# 读入数据集(如果没有则在线下载),并转换成独热编码
# 如果不能下载,则到http://yann.lecun.com/exdb/mnist/进行手工下载,下载后拷贝到当前MNIST_data目录下
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

x = tf.placeholder(tf.float32, [None, 784])  # 占位符,输入
y = tf.placeholder(tf.float32, [None, 10])  # 占位符,输出

W = tf.Variable(tf.random_normal([784, 10]))  # 权重
b = tf.Variable(tf.zeros([10]))  # 偏置值

# 构建模型
pred_y = tf.nn.softmax(tf.matmul(x, W) + b)  # softmax分类
print("pred_y.shape:", pred_y.shape)
# 损失函数
cross_entropy = -tf.reduce_sum(y * tf.log(pred_y),
                               reduction_indices=1)  # 求交叉熵
cost = tf.reduce_mean(cross_entropy)  # 求损失函数平均值

# 参数设置
lr = 0.01
# 梯度下降优化器
optimizer = tf.train.GradientDescentOptimizer(lr).minimize(cost)

training_epochs = 200
batch_size = 100
saver = tf.train.Saver()
model_path = "../model/mnist/mnist_model.ckpt"  # 模型路径

# 启动session
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    # 循环开始训练
    for epoch in range(training_epochs):
        avg_cost = 0.0
        total_batch = int(mnist.train.num_examples / batch_size)  # 计算总批次

        # 遍历全数据集
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)  # 读取一个批次样本
            params = {x: batch_xs, y: batch_ys}  # 训练参数

            o, c = sess.run([optimizer, cost], feed_dict=params)  # 执行训练

            avg_cost += (c / total_batch)  # 求平均损失值

        print("epoch: %d, cost=%.9f" % (epoch + 1, avg_cost))

    print("Finished!")

    # 模型评估
    correct_pred = tf.equal(tf.argmax(pred_y, 1), tf.argmax(y, 1))
    # 计算准确率
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
    print("accuracy:", accuracy.eval({x: mnist.test.images,
                                      y: mnist.test.labels}))
    # 将模型保存到文件
    save_path = saver.save(sess, model_path)
    print("Model saved:", save_path)

# 测试模型
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    saver.restore(sess, model_path)  # 加载模型

    batch_xs, batch_ys = mnist.test.next_batch(2)  # 读取2个测试样本
    output = tf.argmax(pred_y, 1)  # 预测结果值

    output_val, predv = sess.run([output, pred_y],  # 操作
                                 feed_dict={x: batch_xs})  # 参数

    print("预测结论:\n", output_val, "\n")
    print("实际结果:\n", batch_ys, "\n")
    print("预测概率:\n", predv, "\n")

    # 显示图片
    im = batch_xs[0]  # 第1个测试样本数据
    im = im.reshape(-1, 28)
    pylab.imshow(im)
    pylab.show()

    im = batch_xs[1]  # 第2个测试样本数据
    im = im.reshape(-1, 28)
    pylab.imshow(im)
    pylab.show()

20. 利用CNN实现服饰识别

# 在fashion_mnist数据集实现服饰识别import tensorflow as tffrom tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_setsclass FashionMnist():    out_featrues1 = 12  # 第一个组卷积池化层输出特征数量(等于第一个卷积层卷积核数量)    out_featrues2 = 24  # 第二个组卷积池化层输出特征数量(等于第二个卷积层卷积核数量)    con_neurons = 512 # 全连接层神经元数量    def __init__(self, path):        """        构造方法        :param path:指定数据集路径        :return:        """        self.sess = tf.Session() # 会话        self.data = read_data_sets(path, one_hot=True) # 读取样本文件对象    def init_weight_variable(self, shape):        """        初始化权重方法        :param shape:指定初始化张量的形状        :return:经过初始化后的张量        """        inital = tf.truncated_normal(shape, stddev=0.1) # 截尾正态分布        return tf.Variable(inital)    def init_bias_variable(self, shape):        """        初始化偏置        :param shape:指定初始化张量的形状        :return:经过初始化后的张量        """        inital = tf.constant(1.0, shape=shape)        return tf.Variable(inital)    def conv2d(self, x, w):        """        二维卷积方法        :param x:原始数据        :param w:卷积核        :return:返回卷积后的结果        """        # input : 输入数据[batch, in_height, in_width, in_channels]        # filter : 卷积窗口[filter_height, filter_width, in_channels, out_channels]        # strides: 卷积核每次移动步数,对应着输入的维度方向        # padding='SAME' : 输入和输出的张量形状相同        return tf.nn.conv2d(x,  # 原始数据                            w, # 卷积核                            strides=[1, 1, 1, 1], # 各个维度上的步长值                            padding="SAME") # 输入和输出矩阵大小相同    def max_pool_2x2(self, x):        """        池化函数        :param x:原始数据        :return:池化后的数据        """        return tf.nn.max_pool(x,# 原始数据                              ksize=[1, 2, 2, 1], # 池化区域大小                              strides=[1, 2, 2, 1], # 各个维度上的步长值                              padding="SAME")    def create_conv_pool_layer(self, input, input_features, out_features):        """        卷积、激活、池化层        :param input:原始数据        :param input_features:输入特征数量        :param out_features:输出特征数量        :return:卷积、激活、池化层后的数据        """        filter = self.init_weight_variable([5, 5, input_features, out_features])#卷积核        b_conv = self.init_bias_variable([out_features]) # 偏置,数量和卷积输出大小一致        h_conv = tf.nn.relu(self.conv2d(input, filter) + b_conv)#卷积,结果做relu激活        h_pool = self.max_pool_2x2(h_conv) #对激活操作输出做max池化        return h_pool    def create_fc_layer(self, h_pool_flat, input_featrues, con_neurons):        """        创建全连接层        :param h_pool_flat:输入数据,经过拉伸后的一维张量        :param input_featrues:输入特征大小        :param con_neurons:神经元数量        :return:全连接        """        w_fc = self.init_weight_variable([input_featrues, con_neurons])#输出数量等于神经元数量        b_fc = self.init_bias_variable([con_neurons]) #偏置数量等于输出数量        h_fc1 = tf.nn.relu(tf.matmul(h_pool_flat, w_fc) + b_fc) #计算wx+b并且做relu激活        return h_fc1    def build(self):        """        组建CNN        :return:        """        # 输入数据,N个28*28经过拉伸后的张量        self.x = tf.placeholder(tf.float32, shape=[None, 784])        x_image = tf.reshape(self.x, [-1, 28, 28, 1]) # 28*28单通道        self.y_ = tf.placeholder(tf.float32, shape=[None, 10]) # 标签,对应10个类别        # 第一组卷积池化层        h_pool1 = self.create_conv_pool_layer(x_image, 1, self.out_featrues1)        # 第二组卷积池化层        h_pool2 = self.create_conv_pool_layer(h_pool1, # 上一层输出作为输入                                  self.out_featrues1, # 上一层输出特征数量作为输入特征数量                                  self.out_featrues2)# 第二层输出特征数量        # 全连接层        h_pool2_flat_features = 7 * 7 * self.out_featrues2 # 计算特征点数量        h_pool2_flat = tf.reshape(h_pool2, [-1, h_pool2_flat_features])#拉升成一维张量        h_fc = self.create_fc_layer(h_pool2_flat, # 输入                                    h_pool2_flat_features, # 输入特征数量                                    self.con_neurons) # 输出特征数量        # dropout层(通过随机丢弃一部分神经元的更新,防止过拟合)        self.keep_prob = tf.placeholder("float") # 丢弃率        h_fc1_drop = tf.nn.dropout(h_fc, self.keep_prob)        # 输出层        w_fc = self.init_weight_variable([self.con_neurons, 10])#512行10列,产生10个输出        b_fc = self.init_bias_variable([10]) # 10个偏置        y_conv = tf.matmul(h_fc1_drop, w_fc) + b_fc # 计算wx+b, 预测结果        # 评价        correct_prediction = tf.equal(tf.argmax(y_conv, 1),#取出预测概率中最大的值的索引                                      tf.argmax(self.y_, 1))#取出真实概率中最大的值的索引        # 将上一步得到的bool类型数组转换为浮点型,并求准确率        self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))        # 损失函数        loss_func = tf.nn.softmax_cross_entropy_with_logits(labels=self.y_,#真实值                                                            logits=y_conv)#预测值        cross_entropy = tf.reduce_mean(loss_func)        # 优化器        optimizer = tf.train.AdamOptimizer(0.001)        self.train_step = optimizer.minimize(cross_entropy)    def train(self):        self.sess.run(tf.global_variables_initializer()) #初始化        merged = tf.summary.merge_all() #摘要合并        batch_size = 100        print("beging training...")        for i in range(10): # 迭代训练            total_batch = int(self.data.train.num_examples / batch_size)#计算批次数量            for j in range(total_batch):                batch = self.data.train.next_batch(batch_size)#获取一个批次样本                params = {self.x: batch[0], self.y_:batch[1],#输入、标签                          self.keep_prob: 0.5} #丢弃率                t, acc = self.sess.run([self.train_step, self.accuracy],# op                                       params) # 喂入参数                if j % 100 == 0:                    print("epoch: %d, pass: %d, acc: %f"  % (i, j, acc))    # 评价    def eval(self, x, y, keep_prob):        params = {self.x: x, self.y_: y, self.keep_prob: 1.0}        test_acc = self.sess.run(self.accuracy, params)        print('Test accuracy %f' % test_acc)        return test_acc    # 关闭会话    def close(self):        self.sess.close()if __name__ == "__main__":    mnist = FashionMnist('FASHION_MNIST_data/')    mnist.build()    mnist.train()    print('\n----- Test -----')    xs, ys = mnist.data.test.next_batch(100)    mnist.eval(xs, ys, 0.5)    mnist.close()

你可能感兴趣的:(深度学习,opencv,python)