写在前言----
这是我第一次去尝试写自己的博客,想把自己的学习历程好好记录下来,以前学习的时候都没能好好认真的学,代码大部分都是用的同学的,没有自食其力,发现自己只会一些很基本的东西,学习了python近两年,学了人工智能基础,数据结构算法,python基础,模式识别,数据挖掘等课程,但都没能好好有一个记录或者说是一个自己去探索的过程,导致脑袋空空,可以说是会一点皮毛,但不精通,但这并不是我想要的,我想通过自己的努力慢慢把以前落下的重新拾起来,一步一个脚印慢慢积累。
现在是新的一个学期,这是我们第一次的实验课,虽然对于很多人来说可能是很简单,但是对于我来说是一个回顾也同时是一个新探索的过程,我会把自己学习到的东西分享给大家,会去探索,去创新,去创造属于自己的东西
1、导入cv2库,用于图像处理。
2、导入numpy库,用于数组计算。
3、导入matplotlib库的pyplot模块,用于绘图。
4、导入math,用于数学计算。
5、导入PIL库的Image、ImageDraw和ImageFont模块。
6、构建图片添加中文字符函数ImgText_CN(),其中的参数为图像矩阵、文字、左上角坐标、颜色和字体大小。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import math
from PIL import Image, ImageDraw, ImageFont
构建图片添加中文字符函数ImgText_CN(),其中的参数为图像矩阵、文字、左上角坐标、颜色和字体大小。
def ImgText_CN(img, text, left, top, textColor=(255, 0, 0), textSize=20):
if (isinstance(img, np.ndarray)): #判断是否为OpenCV图片类型
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img)
fontText = ImageFont.truetype(font='simhei.ttf',size=textSize, index=0)
#font='simhei.ttf'微软雅黑文件
draw.text((left, top), text, textColor, font=fontText) #写文字
return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
使用cv2.imshow()函数展示图像。
使用cv2.waitKey()函数设置等待键盘输入,不输入则无限等待。
使用cv2.destroyAllWindows()函数关闭所有窗口。
# 读取图片
key_img = cv2.imread(r"C:\Users\11657\Desktop\data\key.jpg")
res1 = ImgText_CN(key_img, '钥匙', 5, 5, textColor=(255, 0, 0), textSize=20)
#绘制文字
cv2.imshow('key',res1)
cv2.waitKey()
cv2.destroyAllWindows
OpenCV中提供blur函数来进行图像均值滤波,只取内核区域下所有像素的平均值并替换中心元素,其对应参数如下。
cv2.blur(img, ksize)
img:原图像
ksize:核大小
返回值:图像矩阵
# 均值滤波
img = cv2.blur(key_img, (3, 3))
res2 = ImgText_CN(img,'均值滤波', 5, 5, textColor=(255, 0, 0), textSize=20)
cv2.imshow('key',res2)
cv2.waitKey()
cv2.destroyAllWindows()
OpenCV中提供medianBlur函数来进行图像中值滤波,相当于将方框内的个值进行排序,取中值作为当前值,其对应参数如下。
cv2.medianBlur(img, k)
img:原图像
k:方框的尺寸
返回值:图像矩阵
# 中值滤波
img = cv2.medianBlur(key_img, 5)
res3 = ImgText_CN(img, '中值滤波', 5, 5, textColor=(255, 0, 0), textSize=20)
cv2.imshow('key',res3)
cv2.waitKey()
cv2.destroyAllWindows()
OpenCV中提供GaussianBlur函数来进行图像高斯滤波,其对应参数如下。
cv2.GuassianBlur(img, ksize, sigmaX, sigmaY)
img:原图像
ksize:核大小
sigmaX和sigmaY:分别表示X和Y方向的标准偏差,如果仅指定了sigmaX,则sigmaY与sigmaX相同。如果两者都为零,则根据内核大小计算它们。
返回值:图像矩阵
# 高斯滤波
img = cv2.cv2.GaussianBlur(key_img,(5,5), sigmaX=0, sigmaY=0)
res4 = ImgText_CN(img, '高斯滤波', 5, 5, textColor=(255, 0, 0), textSize=20)
cv2.imshow('key',res4)
cv2.waitKey()
cv2.destroyAllWindows()
OpenCV中提供bilateralFilter函数来进行图像双边滤波,其对应参数如下。
cv2.bilateralFilter(img, d, sigmaColor, sigmaSpace)
img:原图像
d:邻域直径
sigmaColor:空间高斯函数标准差,参数越大,临近像素将会在越远的地方越小
sigmaSpace:灰度值相似性高斯函数标准差,参数越大,那些颜色足够相近的的颜色的影响越大
返回值:图像矩阵
# 双边滤波
img = cv2.bilateralFilter(key_img, 5, sigmaColor=5, sigmaSpace=5)
res5 = ImgText_CN(img, '双边滤波', 5, 5, textColor=(255, 0, 0), textSize=20)
cv2.imshow('key',res5)
cv2.waitKey()
cv2.destroyAllWindows()
# 不同滤波的边缘检测对比
img = cv2.Canny(key_img,60,120)
res6 = ImgText_CN(img, '均值边缘检测,中值边缘检测', 5, 5, textColor=(255, 0, 0), textSize=20)
cv2.imshow('key',res6)
cv2.waitKey()
cv2.destroyAllWindows()
个人感觉前面没啥变化,就最后一张变化比较大
此处的图像处理,这里全部都用的灰度图像处理的也就是说,需要将图像转化为灰度图像
mg = cv2.cvtColor(mg,cv2.COLOR_BGR2GRAY
灰度直方图是图像灰度级的函数,用来描述每个灰度级在图像矩阵中的像素个数或者占有率。
自定义计算灰度直方图函数calcGrayHist(),设定图像I作为输入参数。
(1)获得图像的长宽。
(2)创建1*256的全零矩阵。
(3)建立双层循环,根据图像个像素点数值,统计不同像素值的出现次数。
(4)将统计结果作为函数返回值。
def calcGrayHist(I): # 计算灰度直方图
#转化为灰度图
#img = cv2.cvtColor(I,cv2.COLOR_BGR2GRAY)
#显示灰度图
#cv2.imshow('gray_img',img)
#cv2.waitKey(0)
#灰度图像矩阵的长,宽
#rows,cols = img.shape
rows,cols = I.shape[:2]
print(I.shape)
#存储灰度直方图
grayHist = np.zeros([256],np.uint64)
for r in range(rows):
for c in range(cols):
grayHist[I[r][c]] += 1
#print(grayHist)
return grayHist
img = cv2.imread(r"C:\Users\11657\Desktop\data\5.jpg")
cv2.imshow('5',img)
cv2.waitKey()
cv2.destroyAllWindows()
y = calcGrayHist(img)
x = np.arange(256)
# 绘制灰度直方图
plt.plot(x,y,'k-', linewidth=2)
plt.xlabel("gray Label")
plt.ylabel("number of pixels")
plt.show()
1、原图像矩阵乘以2.0,并赋值给变量out。
2、变量out的元素大于255的值截断为255。
3、使用np.around()函数对out进行四舍五入精度计算。
4、使用astype()方法把out类型转为np.uint8。
# 线性变换
imggray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
out = imggray*2
# 进行数据截断,大于255的值截断为255
out[out > 255] = 255
# 数据类型转换
out = np.around(out)
out = np.asarray(out, np.uint8)
cv2.imshow('img',img)
cv2.imshow('out',out)
# 等待键盘输入,不输入则无限等待
# 关闭所有窗口
cv2.waitKey()
cv2.destroyAllWindows()
OpenCV中提供normalize函数来进行图像归一化,其对应参数如下。
cv2.normalize(src, dst, alpha, beta, norm_type, dtype, mask)
src:输入数组
dst:与src大小相同的输出数组
alpha:在范围规格化的情况下,规格化到或更低范围边界的标准值
beta:范围归一化情况下的上限范围边界,不用于规范化
norm_type:规范化类型
dtype:如果为负值,则输出数组的类型与src相同;否则,其通道数与src相同
mask:可选操作掩码
# 直方图正规化
out1 = np.zeros([426,640,3],np.uint8)
out1 = cv2.normalize(img,out1,255,0,norm_type=cv2.NORM_MINMAX,dtype=cv2.CV_8U)
out1 = cv2.cvtColor(out1,cv2.COLOR_BGR2GRAY)
cv2.imshow('imggrat',imggray)
cv2.imshow('out1',out1)
# 等待键盘输入,不输入则无限等待
# 关闭所有窗口
cv2.waitKey()
cv2.destroyAllWindows()
# 伽马变换
# 图像归一化
gamma = 0.4
fi = np.power(imggray/255.0,gamma)
cv2.imshow('imggray',imggray)
cv2.imshow('fi',fi)
# 等待键盘输入,不输入则无限等待
# 关闭所有窗口
cv2.waitKey()
cv2.destroyAllWindows()
OpenCV中提供equalizeHist函数来进行直方图均衡化,其对应参数如下。
cv2.equalizeHist(image,channels,mask,histSize,ranges)
image:待计算直方图的图像,需用[]包裹
channels:指定待计算直方图的图像的哪一通道用来计算直方图,RGB图像可以指定[0,1,2],灰度图像只有[0],需用[]包裹
mask:掩码,可以指定图像的范围,如果是全图,默认为none
hitsize:直方图的灰度级数,例如[0,255]一共256级,故参数为256,需用[]包裹
range:像素值范围,为[0,255]
返回值:直方图矩阵
全局直方图均衡化
# 如果想要对图片做均衡化,必须将图片转换为灰度图像
dst = cv2.equalizeHist(imggray)
cv2.imshow('imggray',imggray)
cv2.imshow("global equalizeHist", dst)
cv2.waitKey()
cv2.destroyAllWindows()
OpenCV中提供createCLAHA函数来生成自适应均衡化图像,其对应参数如下。
cv2.createCLAHA(clipLimit=5.0, tileGridSize=(8, 8))
clipLimit:颜色对比度的阈值
titleGridSize:进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作
# 限制对比度的自适应直方图均衡化
# 创建CLAHE对象
clahe = cv2.createCLAHE(clipLimit=5.0,tileGridSize=(8, 8))
dst = clahe.apply(gray)#需要先将其转化为灰度图像
cv2.imshow('imggray',imggray)
cv2.imshow('imgclahe',dst)
cv2.waitKey()
cv2.destroyAllWindows()
# 读取图片
image = cv2.imread(r"C:\Users\11657\Desktop\data\key.jpg")
# 进行高斯模糊操作
image1 = cv2.GaussianBlur(image,(5,5), sigmaX=0, sigmaY=0)
# 进行图片灰度化
image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
print(image1.shape)
rett,image1 = cv2.threshold(image1,50,255,cv2.THRESH_BINARY)
# 图像的阈值分割处理,即将图像处理成非黑即白的二值图像
# 将阈值分割处理后的图片命名为“image1”显示出来
cv2.imshow('image',image)
cv2.imshow('image1',image1)
cv2.waitKey()
cv2.destroyAllWindows()
print(image1.shape)
# 二值图像的反色处理,将图片像素取反
# 返回图片大小
def access_pixels(image): # 获取图片高宽通道
#print(image.shape)
height = image.shape[0]
width = image.shape[1]
# height,width=image.shape
# 也可以直接写成:
# height, width, channels = image.shape[:]
#print("width: %s, height: %s, channels: %s"%(width, height, channels))
new_image = image.copy() # 复制image图片
for row in range(height):
for col in range(width):
#for c in range(channels):
# pv = new_image[row][ col]
new_image[row][col] = 255 - new_image[row][col] # 图像反转
return new_image
image2=access_pixels(image1)
cv2.imshow('image',image)
cv2.imshow('image2',image2)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 边缘提取,使用Canny函数
image3 = cv2.Canny(image2,80,255)
cv2.imshow('image3',image3)
cv2.waitKey()
cv2.destroyAllWindows()
#再次对图像进行反色处理使提取的边缘为黑色,其余部分为白色,方法同image2
image3 = access_pixels(image3)
cv2.imshow('image3',image3)
cv2.waitKey()
cv2.destroyAllWindows()
个人觉得本次实验还比较轻松,主要就两个点
第一个就是#font='simhei.ttf'微软雅黑文件,这个文件是可以用自己电脑的字体文件,我之前下载了一个文件导入不了,问了身边的朋友才知道
第二个就是边缘检测应该将其都转换为灰度图像再处理