OpenCV 和 Tensorflow
OpenCV是计算机视觉库,Tensorflow是深度学习框架。
OpenCV包含了大量的图像处理和计算机视觉的算法,但是在机器学习方面明显不足,ML模块只有SVM,MLP,kNN等有限的几种算法。dnn模块也是调用别的框架。
Tensorflow是专为深度学习而生,可以方便的实现各种深度学习算法。
二者不属于同一领域,做视觉用OpenCV,做深度学习用Tensorflow。或者二者结合做图像识别等等。
RGB
RGB:表示三通道,红色通道,绿色通道,蓝色通道。
三个颜色是原始颜色,能够组成所有的颜色。每个通道的值为0-255,0表示黑,255表示白。
在代码中,读取图片转换成为三维数组,通道为BGR显示。
积分图像
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
img = cv2.imread('lena.png')
# 将图像变成单通道,处理单通道和多通道的难度差不多
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 获取积分值,表示获得图像上的某一点到该图像左上角所构成的子图的所有像素之和,就是该点的积分值
integral_img = cv2.integral(img)
# 将积分值除以最大值,范围变成 0 - 1
integral_img = integral_img / integral_img.max()
# 将积分值变成0-255,方便画图
integral_img = (integral_img * 255).astype(np.uint8)
# 画图
plt.figure(figsize=(7,5))
# 第一个子图
plt.subplot(1,2,1)
plt.imshow(img, cmap='gray')
plt.title('原始图像', fontsize=14)
# 第二个子图
plt.subplot(1,2,2)
plt.imshow(integral_img, cmap='gray')
plt.title('积分图像', fontsize=14)
# 自动调整子图参数,使之填充整个图像区域
plt.tight_layout(pad=1)
plt.show()
图像的直方图
import cv2
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
img = cv2.imread('lena.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(9,5))
plt.subplot(1,2,1)
plt.imshow(img)
plt.title('读入图像', fontsize=14)
print(img)
print(img.flatten())
plt.subplot(1,2,2)
# 画直方图,img.flatten():将所有的像素转化成为一个一维数组,bins:将数组分成128份
plt.hist(img.flatten(), bins=128, color='g', edgecolor='k', lw=0.3)
plt.title('图像直方图', fontsize=14)
plt.show()
# cv2.namedWindow('Image', cv2.WINDOW_AUTOSIZE)
# cv2.imshow('Image', img)
# cv2.waitKey(0)
直方图的均衡化
- 直方图的均衡化,就是获取像素值变换函数,根据像素值变换函数的映射关系,获得真实图像的img.flatten()作为x值,根据映射关系获取y的值的过程的到均衡化后的img_set。
- 像素值变化函数的获取看以下代码的过程。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
img = cv2.imread('lena.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# plt.imshow(img)
# plt.show()
np.set_printoptions(suppress=True)
# img.flatten()将矩阵变成一个一维数组,bins:表示分成多少份,输出直方图,获得im_hist:每一份占整体的比率,bins:份数
img_hist, bins = np.histogram(img.flatten(), bins=np.arange(256), normed=True)
print(img_hist)
print(bins)
# 将一维数组img_hist进行累计加和,例如[1,2,3,4] 累计加和后 [1,3,6,10]
cdf = img_hist.cumsum() # 累计概率(频率)分布
print(cdf)
# 进行拉伸的过程
cdf = 255 * cdf
print(cdf)
plt.figure(figsize=(5,4))
plt.plot(bins[:-1], cdf, lw=3, color='r')
plt.plot(bins[[0,-1]], cdf[[0, -1]], lw=1, color='g', linestyle='--')
plt.title('像素值变换函数', fontsize=14)
# plt.show()
# 均衡化图像
img_eq = np.interp(img.flatten(), bins[:-1], cdf)
#img_eq.astype(np.uint8) 修改nparray的数据类型
img_eq = img_eq.astype(np.uint8).reshape(img.shape)
print(img_eq.shape)
print('插值后:', img_eq)
# plt.imshow(img_eq)
# plt.show()
plt.figure(figsize=(9,7))
plt.subplot(2,2,1)
plt.imshow(img)
plt.title('原始图像', fontsize=14)
plt.subplot(2,2,2)
plt.hist(img.flatten(), np.arange(256))
plt.title('原始图像直方图', fontsize=14)
plt.subplot(2,2,3)
plt.imshow(img_eq)
plt.title('均衡化图像', fontsize=14)
plt.subplot(2,2,4)
plt.hist(img_eq.flatten(), np.arange(256))
plt.title('均衡化图像的直方图', fontsize=14)
plt.tight_layout(pad=1)
plt.show()
图像的高斯模糊
高斯模糊:可以用作卷积神经网络的卷积核,用不同的卷积核,会得到不同的样子。
import cv2
from scipy.ndimage import filters
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
# 表示方差,方差值越大,表示图像越平缓
sigmas = [1, 2, 3, 4, 5]
img = cv2.imread('lena.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(8, 6))
plt.subplot(2, 3, 1)
plt.imshow(img)
plt.title('原始图像')
for j, sigma in enumerate(sigmas, start=2):
# np.empty(shape)创建一个给定形状的新的数组。
img_gaussian = np.empty(img.shape)
for i in range(3):
# 使用高斯模糊filters.gaussian_filter()函数,生成一个新的图像(矩阵)
# sigma方差值越大,越分散,越模糊。
img_gaussian[:, :, i] = filters.gaussian_filter(img[:, :, i], sigma)
# print(img_gaussian)
img_gaussian = img_gaussian.astype(np.uint8)
plt.subplot(2,3,j)
plt.title('$\sigma$=%.1f' % sigma)
plt.imshow(img_gaussian)
plt.tight_layout( rect=(0,0,1,0.95))
plt.suptitle('高斯模糊 - 方差', fontsize=14)
plt.show()
结果
采用不同的卷积核(图片的模糊处理),进行卷积,调用convolve函数,代码实现
#!/usr/bin/python
# -*- coding:utf-8 -*-
import numpy as np
import os
from PIL import Image
#
def convolve(image, weight):
height, width = image.shape
h, w = weight.shape
height_new = height - h + 1
width_new = width - w + 1
image_new = np.empty((height_new, width_new), dtype=np.float)
for i in range(height_new):
for j in range(width_new):
image_new[i,j] = np.sum(image[i:i+h, j:j+w] * weight)
# clip()函数的功能是把数组image_new中小于min(0)的值设置为min,大于max(255)的值设置为max。
image_new = image_new.clip(0, 255)
# np.rint()将数组的元素四舍五入为最接近的整数。
image_new = np.rint(image_new).astype('uint8')
return image_new
# image_new = 255 * (image_new - image_new.min()) / (image_new.max() - image_new.min())
if __name__ == "__main__":
A = Image.open("./lena.png", 'r')
print(A)
output_path = './Convolutional/'
# 如果目录不存在,则创建目录。
if not os.path.exists(output_path):
os.mkdir(output_path)
a = np.array(A)
print(a.shape)
print(a)
# ones()返回一个给定形状或者类型的新的数组,并填充1
avg3 = np.ones((3, 3))
avg3 /= avg3.sum()
print(avg3)
avg5 = np.ones((5, 5))
avg5 /= avg5.sum()
avg20 = np.ones((20, 20))
avg20 /= avg20.sum()
# 5x5的高斯模糊,卷积核
gauss = np.array(([0.003, 0.013, 0.022, 0.013, 0.003],
[0.013, 0.059, 0.097, 0.059, 0.013],
[0.022, 0.097, 0.159, 0.097, 0.022],
[0.013, 0.059, 0.097, 0.059, 0.013],
[0.003, 0.013, 0.022, 0.013, 0.003]))
soble_x = np.array(([-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]))
soble_y = np.array(([-1, -2, -1],
[0, 0, 0],
[1, 2, 1]))
soble = np.array(([-1, -1, 0],
[-1, 0, 1],
[0, 1, 1]))
prewitt_x = np.array(([-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]))
prewitt_y = np.array(([-1, -1,-1],
[0, 0, 0],
[1, 1, 1]))
prewitt = np.array(([-2, -1, 0],
[-1, 0, 1],
[0, 1, 2]))
laplacian4 = np.array(([0, -1, 0],
[-1, 4, -1],
[0, -1, 0]))
laplacian8 = np.array(([-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]))
weight_list = ('avg3', 'avg5', 'avg20', 'gauss', 'soble_x', 'soble_y', 'soble', 'prewitt_x', 'prewitt_y', 'prewitt', 'laplacian4', 'laplacian8')
print('梯度检测:')
for weight in weight_list:
print(weight, 'R', end=' ')
#eval('avg3') 将avg3二维矩阵输出,eval()将表达式的值计算出来并输出
R = convolve(a[:, :, 0], eval(weight))
print('G', end=' ')
G = convolve(a[:, :, 1], eval(weight))
print('B')
B = convolve(a[:, :, 2], eval(weight))
# stack按照轴进行堆叠成新的格式的矩阵
I = np.stack((R, G, B), axis=2)
# if weight not in ('avg3', 'avg5', 'avg20', 'gauss'):
# I = 255 - I
# fromarray(I)将数组I转化成图像格式,调用save()保存下来
Image.fromarray(I).save(output_path + weight + '.png')
股票预测案例
# !/usr/bin/python
# -*- coding:utf-8 -*-
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
if __name__ == "__main__":
stock_max, stock_min, stock_close, stock_amount = np.loadtxt('SH600000.txt', delimiter='\t', skiprows=2, usecols=(2, 3, 4, 5), unpack=True)
N = 100
stock_close = stock_close[:N]
# 指数移动平均线估计,做一个5日均线,5天的收盘价/5
n = 5
weight = np.ones(n)
weight /= weight.sum()
print('weight = ', weight)
# 进行一维的卷积,mode=‘valid’,表示只有有效的值才会进行卷积,默认mode='full'
stock_sma = np.convolve(stock_close, weight, mode='valid') # simple moving average
weight = np.linspace(1, 0, n)
weight = np.exp(weight)
weight /= weight.sum()
print('EMA weight = ', weight)
# 指数平均移动数
stock_ema = np.convolve(stock_close, weight, mode='valid') # exponential moving average
t = np.arange(n-1, N)
# f(x)=a1*x^m+...+am*x+a_m+1 根据t,stock_ema的(x,y)坐标,最高次幂为5 求解系数a,得到poly
poly = np.polyfit(t, stock_ema, 5)
print(poly)
t = np.arange(n-1, N)
# 根据系数poly,根据x的值t,获的y值stock_ema_hat
stock_ema_hat = np.polyval(poly, t)
# 画图
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
plt.figure(facecolor='w')
plt.plot(np.arange(N), stock_close, 'ro-', linewidth=2, label='原始收盘价', mec='k')
t = np.arange(n-1, N)
plt.plot(t, stock_sma, 'b-', ms=6, linewidth=2, label='简单移动平均线')
plt.plot(t, stock_ema, 'g-', linewidth=2, label='指数移动平均线')
# 给图加上图例
plt.legend(loc='upper right')
plt.title('股票收盘价与滑动平均线MA', fontsize=15)
plt.grid(b=True, ls=':', color='#404040')
plt.show()
print(plt.figure(figsize=(7, 5), facecolor='w'))
plt.plot(np.arange(N), stock_close, 'ro-', linewidth=1, label='原始收盘价', mec='k')
plt.plot(t, stock_ema_hat, '-', color='#4040FF', linewidth=3, label='指数移动平均线估计')
plt.plot(t, stock_ema, 'g-', linewidth=2, label='指数移动平均线')
plt.legend(loc='upper right')
plt.title('滑动平均线MA的估计', fontsize=15)
plt.grid(b=True, ls=':', color='#404040')
plt.show()
图片提取前景案例
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
img = cv2.imread('cloud.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
diff = (3,3,3) #一个元祖,就是一个不可变的列表
# print(type(diff))
mask = np.zeros((img.shape[0]+2, img.shape[1]+2), np.uint8)
ff_img = np.copy(img)
cv2.floodFill(ff_img, mask, (10,10), (255,255,255), diff, diff)
print('img = \n', img)
print('ff_img = \n', ff_img)
plt.figure(figsize=(11,5))
plt.subplot(1,2,1)
plt.imshow(img)
plt.title('原始图像', fontsize=14)
plt.subplot(1,2,2)
plt.imshow(ff_img)
plt.title('提取前景', fontsize=14)
plt.tight_layout(pad=1)
plt.show()