糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 深度学习实验手册

深度学习实验手册

时间:2018-11-23 19:02:29

相关推荐

深度学习实验手册

深度学习实验手册

文章目录

深度学习实验手册一、基础理论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检测芯片瑕疵 三、Tensorflow1. 查看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.7tmp = x1 * w1 + x2 * w2if tmp <= theta:return 0else:return 1print(AND(1, 1))print(AND(1, 0))# 实现逻辑或def OR(x1, x2):w1, w2, theta = 0.5, 0.5, 0.2tmp = x1 * w1 + x2 * w2if tmp <= theta:return 0else:return 1print(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 yprint(XOR(1, 0))print(XOR(0, 1))print(XOR(1, 1))print(XOR(0, 0))

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

from scipy import signalfrom scipy import miscimport matplotlib.pyplot as pltimport numpy as npimport scipy.ndimage as snim = 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数组和设计好的卷积和作二维卷积运算,设计边界处理方式为symmconv_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 miscfrom scipy import signalimport matplotlib.pyplot as pltimport matplotlibimport numpy as npimport scipy.ndimage as snimport cv2import pylabim = cv2.imread("../data/zebra.png",0)flt = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])/2flt2 = np.array([[1,2,1],[0,0,0],[-1,-2,-1]])/2conv_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./simple/ --trusted-host https://pypi.tuna.# 安装opencv贡献库pip3 install --user opencv-contrib-python==3.4.2.16 --index-url https://pypi.tuna./simple/ --trusted-host https://pypi.tuna.

2. OpenCV基本操作

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

# 读取图像import cv2im = 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() # 销毁所有创建的窗口

执行结果:

3. 图像色彩操作

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

# 彩色图像转换为灰度图像示例import cv2im = cv2.imread("../data/Linus.png", 1)cv2.imshow("RGB", im) # 在test窗口中显示图像# 使用cvtColor进行颜色空间变化,COLOR_BGR2GRAY表示BGR to GRAYimg_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) # 彩色图像灰度化cv2.imshow("Gray", img_gray)cv2.waitKey() # 等待用户按键反馈cv2.destroyAllWindows() # 销毁所有创建的窗口

执行结果:

2)色彩通道操作

# 色彩通道操作:通道表示为BGRimport numpy as npimport cv2im = cv2.imread("../data/opencv2.png")print(im.shape)cv2.imshow("im", im)# 取出蓝色通道,当做单通道图像显示b = im[:, :, 0]cv2.imshow("b", b)# 去掉蓝色通道(索引为0的通道)im[:, :, 0] = 0cv2.imshow("im-b0", im)# 去掉绿色通道(索引为1的通道)im[:, :, 1] = 0cv2.imshow("im-b0g0", im)cv2.waitKey()cv2.destroyAllWindows()

执行结果:

3)灰度直方图均衡化

# 直方图均衡化示例import numpy as npimport cv2from matplotlib import pyplot as pltim = 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)彩色亮度直方图均衡化

# 彩色图像亮度直方图均衡化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)色彩提取

从图片中提取特定颜色

import cv2import numpy as npim = 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)二值化与反二值化

# 二值化处理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()

执行结果:

4. 图像形态操作

1)图像翻转

# 图像翻转示例import numpy as npimport cv2im = 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()

执行结果:

2)图像仿射变换

# 图像仿射变换import numpy as npimport cv2def 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()

执行结果:

3)图像缩放

# 图像缩放示例import numpy as npimport cv2im = cv2.imread("../data/Linus.png")cv2.imshow("src", im)h, w = im.shape[:2] # 获取图像尺寸dst_size = (int(w/2), int(h/2)) # 缩放目标尺寸,宽高均为原来1/2resized = cv2.resize(im, dst_size) # 执行缩放cv2.imshow("reduce", resized)dst_size = (200, 300) # 缩放目标尺寸,宽200,高300method = cv2.INTER_NEAREST # 最邻近插值resized = cv2.resize(im, dst_size, interpolation=method) # 执行缩放cv2.imshow("NEAREST", resized)dst_size = (200, 300) # 缩放目标尺寸,宽200,高300method = cv2.INTER_LINEAR # 双线性插值resized = cv2.resize(im, dst_size, interpolation=method) # 执行缩放cv2.imshow("LINEAR", resized)cv2.waitKey()cv2.destroyAllWindows()

执行结果:

4)图像裁剪

import numpy as npimport 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_imgim = 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()

执行结果:

5)图像相加

# 图像相加示例import cv2a = 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()

执行结果:

6)图像相减

# 图像相减运算示例import cv2a = 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()

执行结果:

7)透视变换

# 透视变换import cv2import numpy as npimg = 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()

执行结果:

8)图像腐蚀

# 图像腐蚀import cv2import 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()

执行结果:

9)图像膨胀

# 图像膨胀import cv2import 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()

执行结果:

10)图像开运算

# 开运算示例import cv2import 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 cv2import 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()

执行结果:

12)形态学梯度

# 形态学梯度示例import cv2import numpy as npo = 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()

执行结果:

5. 图像梯度处理

1)模糊处理

# 图像模糊处理示例import cv2import numpy as np## 中值滤波im = cv2.imread("../data/lena.jpg", 0)cv2.imshow("orig", im)# 调用medianBlur中值模糊# 第二个参数为滤波模板的尺寸大小,必须是大于1的奇数,如3、5、7im_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()

执行结果:

2)图像锐化处理

# 图像锐化示例import cv2import numpy as npim = cv2.imread("../data/lena.jpg", 0)cv2.imshow("orig", im)# 锐化算子1sharpen_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)# 锐化算子2sharpen_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()

执行结果:

3)边沿检测

# 边沿检测示例import cv2 as cvim = 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()

执行结果:

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:轮廓检索模式,有以下取值和含义:method:轮廓的近似方法,主要有如下取值:

注意事项

待处理的源图像必须是灰度二值图都是从黑色背景中查找白色对象。因此,对象必须是白色的,背景必须是黑色的在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 cv2import numpy as npim = cv2.imread("../data/3.png")cv2.imshow("orig", im)gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)# 图像二值化处理,将大于阈值的设置为最大值,其它设置为0ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 查找图像边沿:cv2.findContoursimg, 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()

执行结果:

2)绘制矩形包围框

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

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

代码:

# 绘制图像矩形轮廓import cv2import numpy as npim = 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,hprint("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()

执行结果:

3)绘制圆形包围圈

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

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

代码:

# 绘制最小圆形import cv2import numpy as npim = 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()

执行结果:

4)绘制最佳拟合椭圆

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

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

代码:

# 绘制最优拟合椭圆import cv2import numpy as npim = 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()

执行结果:

5)逼近多边形

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

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

代码:

# 构建多边形,逼近轮廓import cv2import numpy as npim = 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()

执行结果:

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 npimport 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键breakelse:breakcap.release()out.release()cv2.destroyAllWindows()

8. 综合案例

1)利用OpenCV实现图像校正

【任务描述】

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

【代码】

# 图像校正示例import cv2import numpy as npim = 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 = approxbreakprint(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()

【执行结果】

2)利用OpenCV检测芯片瑕疵

【任务描述】

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

【代码】

import cv2import numpy as npimport 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 * radiusprint("area:", area)if area > 12:print("度盘表面有缺陷")cv2.waitKey()cv2.destroyAllWindows()

【执行结果】

三、Tensorflow

1. 查看Tensorflow版本

from __future__ import absolute_import, division, print_function, unicode_literals# 导入TensorFlow和tf.kerasimport tensorflow as tffrom tensorflow import keras# 导入辅助库import numpy as npimport matplotlib.pyplot as pltprint(tf.__version__)

2. Helloworld程序

# tf的helloworld程序import tensorflow as tfhello = tf.constant('Hello, world!') # 定义一个常量sess = tf.Session() # 创建一个sessionprint(sess.run(hello)) # 计算sess.close()

3. 张量相加

# 常量加法运算示例import tensorflow as tfimport osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 调整警告级别a = tf.constant(5.0) # 定义常量ab = tf.constant(1.0) # 定义常量ac = 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 tfimport osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 调整警告级别a = tf.constant(5.0) # 定义常量ab = tf.constant(1.0) # 定义常量ac = 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 tfimport osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 调整警告级别a = tf.constant(5.0) # 定义常量ab = tf.constant(1.0) # 定义常量ac = tf.add(a, b)graph = tf.get_default_graph() # 获取缺省图print(graph)graph2 = tf.Graph()print(graph2)with graph2.as_default(): # 在指定图上创建opd = tf.constant(11.0)with tf.Session(graph=graph2) as sess:print(sess.run(d)) # 执行计算# print(sess.run(c)) # 报错

6. 查看张量属性

# 创建多个图,指定图运行import tensorflow as tfimport osos.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 tfx = 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''' 变量OP1. 变量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运行opsess.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) #### 运行合并摘要opfw.add_summary(summary, i) #### 写入文件print(i, ":", i, "weight:", weight.eval(), " bias:", bias.eval())

15. 模型保存与加载

# 模型保存示例import tensorflow as tfimport 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() #实例化Saverwith tf.Session() as sess: # 通过Session运行opsess.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) # 运行合并后的tensorfw.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 tfimport osdef 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_batif __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 tfimport osdef 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*200img_resized.set_shape([200, 200, 3]) # 固定样本形状,批处理时对数据形状有要求img_bat = tf.train.batch([img_resized],batch_size=10,num_threads=1)return img_batif __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 pltplt.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 tffrom tensorflow.examples.tutorials.mnist import input_dataimport pylab# 读入数据集(如果没有则在线下载),并转换成独热编码# 如果不能下载,则到/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 = 200batch_size = 100saver = tf.train.Saver()model_path = "../model/mnist/mnist_model.ckpt" # 模型路径# 启动sessionwith tf.Session() as sess:sess.run(tf.global_variables_initializer())# 循环开始训练for epoch in range(training_epochs):avg_cost = 0.0total_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()

如果觉得《深度学习实验手册》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。