# 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))
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-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
# 读取图像
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() # 销毁所有创建的窗口
执行结果:
# 彩色图像转换为灰度图像示例
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() # 销毁所有创建的窗口
执行结果:
# 色彩通道操作:通道表示为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()
执行结果:
# 直方图均衡化示例
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()
执行结果:
# 彩色图像亮度直方图均衡化
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()
执行结果:
从图片中提取特定颜色
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()
执行结果:
# 二值化处理
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()
执行结果:
# 图像翻转示例
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()
执行结果:
# 图像仿射变换
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()
执行结果:
# 图像缩放示例
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()
执行结果:
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()
执行结果:
# 图像相加示例
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()
执行结果:
# 图像相减运算示例
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()
执行结果:
# 透视变换
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()
执行结果:
# 图像腐蚀
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()
执行结果:
# 图像膨胀
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()
执行结果:
# 开运算示例
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)]
# 闭运算示例
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()
执行结果:
# 形态学梯度示例
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()
执行结果:
# 图像模糊处理示例
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()
执行结果:
# 图像锐化示例
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()
执行结果:
# 边沿检测示例
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()
执行结果:
边缘检测虽然能够检测出边缘,但边缘是不连续的,检测到的边缘并不是一个整体。图像轮廓是指将边缘连接起来形成的一个整体,用于后续的计算。
OpenCV提供了查找图像轮廓的函数cv2.findContours(),该函数能够查找图像内的轮廓信息,而函数cv2.drawContours()能够将轮廓绘制出来。图像轮廓是图像中非常重要的一个特征信息,通过对图像轮廓的操作,我们能够获取目标图像的大小、位置、方向等信息。一个轮廓对应着一系列的点,这些点以某种方式表示图像中的一条曲线。
查找轮廓函数:cv2.findContours
语法格式:image,contours,hierarchy=cv2.findContours(image,mode,method)
返回值
参数
取值 | 含义 |
---|---|
cv2.RETR_EXTERNAL | 只检测外轮廓 |
cv2.RETR_LIST | 对检测到的轮廓不建立等级关系 |
cv2.RETR_CCOMP | 检索所有轮廓并将它们组织成两级层次结构,上面的一层为外边界,下面的一层为内孔的边界 |
cv2.RETR_TREE | 建立一个等级树结构的轮廓 |
取值 | 含义 |
---|---|
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近似算法的一种风格 |
注意事项
绘制轮廓:drawContours函数
# 查找图像轮廓
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()
执行结果:
函数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()
执行结果:
函数 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()
执行结果:
函数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()
执行结果:
函数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()
执行结果:
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()
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()
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()
【任务描述】
我们对图像中的目标进行分析和检测时,目标往往具有一定的倾斜角度,自然条件下拍摄的图像,完全平正是很少的。因此,需要将倾斜的目标“扶正”的过程就就叫做图像矫正。该案例中使用的原始图像如下:
【代码】
# 图像校正示例
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()
【执行结果】
【任务描述】
利用图像技术,检测出芯片镀盘区域瑕疵。样本图像中,粉红色区域为镀盘区域,镀盘内部空洞为瑕疵区域,利用图像技术检测镀盘是否存在瑕疵,如果存在则将瑕疵区域标记出来。
【代码】
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()
【执行结果】
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__)
# tf的helloworld程序
import tensorflow as tf
hello = tf.constant('Hello, world!') # 定义一个常量
sess = tf.Session() # 创建一个session
print(sess.run(hello)) # 计算
sess.close()
# 常量加法运算示例
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)) # 执行计算
# 常量加法运算示例
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对象
# 创建多个图,指定图运行
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)) # 报错
# 创建多个图,指定图运行
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)
# 创建张量操作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())
# 张量类型转换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()) #不支持浮点数到字符串直接转换
# 占位符示例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}))
# 改变张量形状示例(重点)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
# 数学计算示例
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())
# 变量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]))
第一步:编写代码
# 变量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
# 线性回归示例
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())
# 模型保存示例
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/")
# 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)
# 图片文件读取示例
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()
# 手写体识别
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()
# 在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()