1. 边缘保留滤波EFP
- 高斯双边滤波:cv.bilateralFilter
- 均值迁移滤波:cv.pyrMeanShiftFiltering
来自这篇博客的定义:
边缘保留滤波EFP:其实就是磨皮效果!!!保留边缘,像素差异小的地方进行模糊处理
import cv2 as cv
import numpy as np
def bi_demo(image):
dst=cv.bilateralFilter(image,0,100,15) #磨皮 高斯双边滤波
cv.imshow('bi_demo',dst)
def shift_demo(image): #磨皮
dst=cv.pyrMeanShiftFiltering(image,0,100,100) #均值迁移,类似油画
cv.imshow('shift_demo',dst)
src=cv.imread('C:\\Users\\22852\\Desktop\\opencv\\data\\girl.jpg')
# cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image:",src)
bi_demo(src)
shift_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
2.直方图均衡化、反向投影
2.1 直方图
对应直方图如下:
通过直方图可以看出图片整体过亮,对比度大,有四个波峰。
代码:
def plot_demo(image):
plt.hist(image.ravel(),256,[0,256])
plt.show()
图像对应三个通道的直方图:
代码:
def image_hist(image):
color=('blue','green','red')
for i ,color in enumerate(color):
hist=cv.calcHist([image],[i],None,[256],[0,256])
plt.plot(hist,color)
plt.xlim([0,256])
plt.show()
2.2 直方图均衡化
- 先转化为灰度图:cv.cvtColor
- 再对灰度图进行直方图均衡化:cv.equalizeHist
代码:
def equalHist_demo(image):#直方图均衡化
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
dst=cv.equalizeHist(gray)
cv.imshow('equalHist_demo',dst)
2.3 局部自适应直方图均衡化
参考
def claHe_demo(image):#局部自适应直方图均衡化
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
clache=cv.createCLAHE(clipLimit=3.0,tileGridSize=(8,8))
dst=clache.apply(gray)
cv.imshow('clahe_demo',dst)
左图为局部自适应直方图均衡化,右图为直方图均衡化:
2.4 直方图的相似性
cv.compareHist:
- cv.HISTCMP_BHATTACHARYYA:巴氏距离
- cv.HISTCMP_CORREL:相关性
- cv.HISTCMP_CHISQR:卡方
- cv.COMP_INTERSECT :相交系数
def create_rgb_hist(image):
h,w,c = image.shape
rgbHist=np.zeros([16*16*16,1],np.float32)
bsize=256/16
for row in range(h):
for col in range(w):
b=image[row,col,0]
g=image[row,col,1]
r=image[row,col,2]
index=int(b/bsize+16+16+g/bsize+16+r/bsize)
rgbHist[index,0]=rgbHist[index,0]+1
return rgbHist
def hist_compare(image1,image2): #比较
hist1=create_rgb_hist(image1)
hist2=create_rgb_hist(image2)
match1=cv.compareHist(hist1,hist2,cv.HISTCMP_BHATTACHARYYA)
match2=cv.compareHist(hist1,hist2,cv.HISTCMP_CORREL)
match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR)
print("巴氏距离: %s,相关性: %s,卡方: %s"%(match1,match2,match3))
巴氏距离: 0.9134011518713788,相关性: 0.06669171290986387,卡方: 468.4549783549784
以上为自己写的直方图,也可以直接用API计算的直方图进行比较和计算
2.5 直方图反向投影
输入图片1:
输出:
代码:
def hist2d_demo(image):
hsv=cv.cvtColor(image,cv.COLOR_BGR2HSV)
hist=cv.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
cv.imshow("hist2d",hist)
plt.imshow(hist,interpolation='nearest')
plt.title('2D Histogram')
plt.show()
cv.calcBackProject:
代码:
def back_project_demo(sample,target):
roi_hsv = cv.cvtColor(sample, cv.COLOR_BGR2HSV)
target_hsv = cv.cvtColor(target, cv.COLOR_BGR2HSV)
roiHist = cv.calcHist([roi_hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
# 归一化: 原始图像,结果图像,映射到结果图像中的最小值,最大值,归一化类型
# cv.NORM_MINMAX对数组的所有值进行转化,使它们线性映射到最小值和最大值之间
# 归一化后的图像便于显示, 归一化后到0~255之间
cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX)
# images, channels, hist, ranges, scale,
dst = cv.calcBackProject([target_hsv], [0, 1], roiHist, [0, 180, 0, 256], 1)
cv.imshow("backProjectionDemo", dst)
3.轮廓发现
3.1 方法1
- 高斯模糊,去噪
- 转化为灰度图
- 转化为二值化图
- findContours:
- cv.RETR_LIST发现所有形状
- cv.RETR_EXTERNAL只发现边缘
- cv.drawContours
代码
def countours_demo(image):
dst=cv.GaussianBlur(image,(3,3),0)#高斯滤波
# img=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
img=cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
ret,binary=cv.threshold(img,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
cv.imshow("binary:",binary)
# binary=edge_demo(binary)
img, contours, hierarchy=cv.findContours(binary,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)#cv.RETR_LIST发现所有形状
# contours, hierarchy=cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)#cv.RETR_EXTERNAL只发现边缘
for i,contour in enumerate(contours):
# cv.drawContours(image,contours,i,[0,0,255])
# cv.drawContours(image,contours,i,[0,0,255],-1)#填充
cv.drawContours(image,contours,i,[0,0,255],2)#填充
print(i)
cv.imshow("circles:",image)
cv.RETR_LIST发现所有形状,线宽2
cv.RETR_EXTERNAL只发现边缘,线宽2
cv.RETR_LIST发现所有形状,线宽2,cv.drawContours:-1填充
3.2 方法2
- 去噪
- 进行candy边缘提取
下图分别是对灰度图、原图、梯度图进行的Canny边缘提取,对灰度图和梯度图进行边缘提取效果由于原图。
def edge_demo(image):
blurred=cv.GaussianBlur(image,(3,3),0)#高斯滤波
#sigmaX Gaussian kernel standard deviation in X direction.
gray=cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
xgrad=cv.Sobel(gray,cv.CV_16SC1,1,0)
ygrad=cv.Sobel(gray,cv.CV_16SC1,0,1)
dst1=cv.Canny(xgrad,ygrad,50,150)
dst2=cv.Canny(image,50,150)
dst3=cv.Canny(gray,50,150)
cv.imshow("Candy Edge_xygrad:",dst1)
cv.imshow("Candy Edge_image:",dst2)
cv.imshow("Candy Edge_gray:",dst3)
return dst1
def countours_demo(image):
dst=cv.GaussianBlur(image,(3,3),0)#高斯滤波
# # img=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
# img=cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
# ret,binary=cv.threshold(img,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
# cv.imshow("binary:",binary)
binary=edge_demo(dst)
img, contours, hierarchy=cv.findContours(binary,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)#cv.RETR_LIST发现所有形状
# img,contours, hierarchy=cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)#cv.RETR_EXTERNAL只发现边缘
for i,contour in enumerate(contours):
# cv.drawContours(image,contours,i,[0,0,255])
# cv.drawContours(image,contours,i,[0,0,255],2)#2为线的宽度
cv.drawContours(image,contours,i,[0,0,255],-1)#填充
print(i)
cv.imshow("circles:",image)
只发现边缘
发现所有形状
填充