滤波方法
均值滤波: 简单的平均卷积操作
img = cv2.imread("man.png",cv2.IMREAD_GRAYSCALE)
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#均值滤波
blur = cv2.blur(img,(3,3))#每3*3进行计算
cv2.imshow("blur",blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
#方框滤波
box = cv2.boxFilter(img,-1,(3,3),normalize = False)#-1表示颜色通道一致 选择是否进行归一化 进行归一化和均值滤波相同 不进行归一化 越界时按255计算
cv2.imshow("box",box)
cv2.waitKey(0)
cv2.destroyAllWindows()
#高斯滤波 离得越近,关系越紧密
aussian = cv2.GaussianBlur(img,(5,5),1)#每3*3进行计算
cv2.imshow("aussian",aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()
#中值滤波 从小到大进行排序,选中间那个值当平滑处理后的结果
median = cv2.medianBlur(img,5)#每5*5进行计算
cv2.imshow("median",median)
cv2.waitKey(0)
cv2.destroyAllWindows()
#展示所有的
res = np.hstack((blur,box,aussian,median)) #hstack 横着拼 vstack 竖着拼
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
canny边缘检测
1.使用高斯滤波器,以平滑图像,滤除噪声
2.计算图像中每个像素点的梯度强度和方向
3.应用非极大值抑制,以消除边缘检测带来的杂散响应
4.应用双阈值检测来确定真实和潜在的边缘
5.通过抑制孤立的弱化边缘最终完成边缘检测
1、高斯滤波核计算
二维高斯分布:
假定中心点的坐标是(0,0),那么取距离它最近的8个点坐标,为了计算,需要设定σ的值。假定σ=1,则高斯滤波核计算如下:
将坐标带入高斯分布得到:
有表中数据可得到结论:中心的值最大,越往外侧值约小。
再归一化处理:我们还要确保这九个值加起来为1(高斯滤波核的特性),这9个点的权重总和等于0.7792,因此给上面9个值还要分别除以0.7792,得到最终的高斯滤波核的值。
2、计算图像的梯度和梯度方向
3、非极大值抑制NMS
在c点的梯度方向(边的垂直方向)做一条线,交点可能没有像素点,则设两个交点为dTmp1,dTmp1,用线性差值法算出两交点像素值,与c点像素值比较,如果c点是最大值则保留c点,否则抛弃。
4、双阈值筛选边缘阈值minvalue, 阈值maxvalue(一般minvalue设为50,maxvalue为3倍的minvalue)
若像素小于阈值minvalue或者大于阈值maxvalue的点扔掉。
若介于minvalue与maxvalue之间,需要分情况,如果像素点在主边缘上则保留,如果与主边缘没有相连则扔掉。
img = cv2.imread("lean.jpg",cv2.IMREAD_GRAYSCALE)
v1=cv2.Canny(img,80,150) #设置阈值
v2=cv2.Canny(img,50,100) #设置更小,边缘信息更多
res = np.hstack((v1,v2))
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像金字塔
将level0级别的图像转换为 level1,level2,level3,level4,图像分辨率不断降低的过程称为向下取样
将level4级别的图像转换为 level3,level2,level1,leve0,图像分辨率不断增大的过程称为向上取样
1、高斯金字塔:
向下采样方法(缩小)将Gi与高斯内核卷积,将所有偶数行和列去除
向上采样方法(放大)将图像在每个方向扩大为原来的两倍,新增的行和列以0填充
使用先前同样的内核(乘以4)与放大后的图像卷积,获得近似值
img = cv2.imread("lean.jpg")
up = cv2.pyrUp(img)
print(up.shape)
down = cv2.pyrDown(img)
print(down.shape)
#先进行up再进行down大小不变,但是像素改变,up和down都要损失一些
up_down = cv2.pyrDown(up)
print(up_down.shape)
res = np.hstack((img,up_down))
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
2、拉普拉斯金字塔
img = cv2.imread("lean.jpg")
down = cv2.pyrDown(img)
down_up = cv2.pyrUp(down)
res = img - down_up
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
轮廓检测方法
边缘零零散散,轮廓是一个整体
cv2.findContours(img,mode,method)
mode:轮廓检索模式
method:轮廓逼近模式
CHAIN_APPROX_SIMPLE :以Freeman的链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)
CHAIN_APPROX_NONE:压缩水平的、垂直的和斜的部分,也就是函数只保留它们的终点部分
#使用二值图像
img = cv2.imread("approx.png")
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) #contours返回的轮廓信息
cv2.imshow("thresh",thresh) #二值处理完的图像
#绘制轮廓
# 需要copy,要不原图会变 传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
draw_img = img.copy()
res = cv2.drawContours(draw_img,contours,-1,(0,0,255),2) #-1是所有轮廓
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
#轮廓特征
cnt = contours[0]
#面积
print(cv2.contourArea(cnt))
#周长 True表示闭合
print(cv2.arcLength(cnt,True))
轮廓特征与近似
img = cv2.imread('approx.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2 转换为二值图
ret, thresh = cv2.threshold(gray, 127, 255,cv2.THRESH_BINARY)
# 3 轮廓提取
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
# 4 轮廓近似
epsilon = 0.1 * cv2.arcLength(cnt, True) #轮廓周长的百分比 越小越贴合
approx = cv2.approxPolyDP(cnt, epsilon, True)
# 5 将轮廓绘制在图像上
draw_img = img.copy()
res = cv2.drawContours(draw_img,[approx],-1,(0,0,255),2)
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
边界矩形
img = cv2.imread('approx.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2 转换为二值图
ret, thresh = cv2.threshold(gray, 127, 255,cv2.THRESH_BINARY)
# 3 轮廓提取
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
x,y,w,h = cv2.boundingRect(cnt)
res = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
rect_area = w * h
extent = float(area)/rect_area
print("轮廓面积与边界矩形",extent)
外接圆
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
res = cv2.circle(img,center,radius,(0,255,0),2)
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()