高通滤波器(HPF)是检测图像的某个区域,跟后根据像素和周围像素的亮度差值来提升(boost)该像素的滤波器。
遇到的问题:第一次运行该程序时还出现了 ImportError: DLL load failed: 找不到指定的模块。
问题原因是numpy没找到支持blas的库。
解决办法:
https://www.lfd.uci.edu/~gohlke/pythonlibs/
下载与自己python版本对应的 numpy+mkl
pip install 此安装文件
import cv2
import numpy as np
from scipy import ndimage
kernel_3x3 = np.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
kernel_5x5 = np.array([[-1, -1, -1, -1, -1],
[-1, 1, 2, 1, -1],
[-1, 2, 4, 2, -1],
[-1, 1, 2, 1, -1],
[-1, -1, -1, -1, -1]])
img = cv2.imread("D:\Algorithm\Learning_OpenCV_3_Computer_Vision_with_Python_Second_Edition_Code\Learning_OpenCV_3_Computer_Vision_with_Python_Second_Edition_Code\Chapter 3_Code\gg.jpeg", 0)
#用特定的核对图像进行 卷积(convolve)
k3 = ndimage.convolve(img, kernel_3x3)
k5 = ndimage.convolve(img, kernel_5x5)
blurred = cv2.GaussianBlur(img, (17,17), 0)
g_hpf = img - blurred
cv2.imshow("3x3", k3)
cv2.imshow("5x5", k5)
cv2.imshow("g_hpf", g_hpf)
cv2.waitKey()
cv2.destroyAllWindows()
Kernel:核是一组权重的集合,应用在源图像的一个区域,并由此生成目标图像的一个像素。
这些滤波器中的值加起来位1,则不改变图像的亮度:若滤波器中的值加起来为0,则会的到一个边缘检测核,把边缘转为白色, 把非边缘区域转为黑色。
Canny边缘检测算法分为五个步骤:使用高斯滤波器降噪、计算梯度、在边缘上使用非最大抑制(NMS)、在检测到的边缘上使用双(double)阈值去除假阳性(false positive)、分析所有边缘及其它们之间的连接以保留真正的边缘并消除不明显的边缘。
import cv2
import numpy as np
img = cv2.imread("D:\Algorithm\Learning_OpenCV_3_Computer_Vision_with_Python_Second_Edition_Code\Learning_OpenCV_3_Computer_Vision_with_Python_Second_Edition_Code\Chapter 3_Code\gg.jpeg")
cv2.imwrite("canny.jpg", cv2.Canny(img, 100, 300))
cv2.imshow("canny", cv2.imread("canny.jpg"))
cv2.waitKey()
cv2.destroyAllWindows()
效果如图:Canny边缘检测算法的两个阈值的动态调整可参考Canny Edge Detection Auto Thresholding
canny函数
(1)若某一像素位置的幅值超过高阈值,该像素被保留为边缘像素。
(2)若某一像素位置的幅值小于低阈值,该像素被排除。
(3)若某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于高阈值的像素时被保留。
cv2.Canny(inputArray,outputArray,double threshold1,double threshold2,int apertureSize=3,bool L2gradient=false)
第一个参数,输入图像,且需为单通道8位图像。
第二个参数,输出的边缘图。
第三个参数,第一个滞后性阈值。用于边缘连接。
第四个参数,第二个滞后性阈值。用于控制强边缘的初始段,高低阈值比在2:1到3:1之间。
第五个参数,表明应用sobel算子的孔径大小,默认值为3。
第六个参数,bool类型L2gradient,一个计算图像梯度幅值的标识,默认值false。**
HoughLines函数成为标准的霍夫变换,HoughLinesP函数则是概率版本的霍夫变换(只分析点的子集并估计这些点都属于一条直线的概率,比标准霍夫变换执行的更快)。
#coding:utf-8
import cv2
import numpy as np
img = cv2.imread("D:\Algorithm\Learning_OpenCV_3_Computer_Vision_with_Python_Second_Edition_Code\Learning_OpenCV_3_Computer_Vision_with_Python_Second_Edition_Code\Chapter 3_Code\gg.jpeg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,120)
minLineLength = 20
maxLineGap = 5
lines = cv2.HoughLinesP(edges,1,np.pi/180,20,minLineLength,maxLineGap)
#以下部分为HoughLinesP函数的参数说明:
##需要处理的图像。
##线段的几何表示rho和theta,一般分别取1和np.pi/180。
##阈值。一般小于该值则会被忽略。
##最小直线长度和最大线段间距。
for x1,y1,x2,y2 in lines[0]:
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv2.imshow("edges", edges)
cv2.imshow("lines", img)
cv2.waitKey()
cv2.destroyAllWindows()
效果如图:
在这段代码当中,HoughLines函数的调用、最小直线长度选择和最大线段间隙的设置都非常重要。HoughLines函数会接收一个又Canny边缘检测滤波器处理过的单通道二值图像。不一定使用Canny滤波器,但是一个经过降噪且只有边缘的图像当作Hough变换的输入会更好。一般采用Canny滤波器。
OpenCV的HoughCircles函数用来检测圆,跟直线检测方法类似。与minLineLength和maxLineGap这两个参数类似,HoughCircles有一个圆心间的最小距离和圆的最小及最大半径。
#coding:utf-8
import cv2
import numpy as np
planets = cv2.imread('D:\Algorithm\planet.jpg')
gray_img = cv2.cvtColor(planets, cv2.COLOR_BGR2GRAY)
img = cv2.medianBlur(gray_img, 5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,120,
param1=100,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# 画圆
cv2.circle(planets,(i[0],i[1]),i[2],(0,255,0),2)
# 画圆心
cv2.circle(planets,(i[0],i[1]),2,(0,0,255),3)
cv2.imwrite("planets_circles.jpg", planets)
cv2.imshow("HoughCirlces", planets)
cv2.waitKey()
cv2.destroyAllWindows()
1.OpenCV的霍夫圆变换函数原型为:HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles
image参数表示8位单通道灰度输入图像矩阵。
method参数表示圆检测方法,目前唯一实现的方法是HOUGH_GRADIENT。
dp参数表示累加器与原始图像相比的分辨率的反比参数。例如,如果dp = 1,则累加器具有与输入图像相同的分辨率。如果dp=2,累加器分辨率是元素图像的一半,宽度和高度也缩减为原来的一半。
minDist参数表示检测到的两个圆心之间的最小距离。如果参数太小,除了真实的一个圆圈之外,可能错误地检测到多个相邻的圆圈。如果太大,可能会遗漏一些圆圈。
circles参数表示检测到的圆的输出向量,向量内第一个元素是圆的横坐标,第二个是纵坐标,第三个是半径大小。
param1参数表示Canny边缘检测的高阈值,低阈值会被自动置为高阈值的一半。
param2参数表示圆心检测的累加阈值,参数值越小,可以检测越多的假圆圈,但返回的是与较大累加器值对应的圆圈。
minRadius参数表示检测到的圆的最小半径。
maxRadius参数表示检测到的圆的最大半径。
2.OpenCV画圆的circle函数原型:circle(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img
img参数表示源图像。
center参数表示圆心坐标。
radius参数表示圆的半径。
color参数表示设定圆的颜色。
thickness参数:如果是正数,表示圆轮廓的粗细程度。如果是负数,表示要绘制实心圆。
lineType参数表示圆线条的类型。
shift参数表示圆心坐标和半径值中的小数位数。
通过轮廓检测可以计算多边形边界、形状逼近和计算感兴趣区域,在Numpy中矩形区域可以通过数组切片来定义。
首先介绍用Numpy创建纯白色背景的过程:
#coding:utf-8
import cv2 as cv
import numpy as np
#因为zero函数创建的数组是一个全0数组,是一个全黑的背景,要是每个像素都是255那就是白色背景啦
def create_image():
img = np.zeros([400, 400, 3], np.uint8)
img[:, :, 0] = np.zeros([400, 400]) + 255
img[:, :, 1] = np.ones([400, 400]) + 255
img[:, :, 2] = np.ones([400, 400]) * 255
cv.imshow("iamge", img)
img2 = np.zeros([400, 400, 3], np.uint8)+255
cv.imshow("iamge2", img2)
cv.waitKey(0)
create_image()
再创建简单的形状通过轮廓检测算法去识别图像轮廓:
#coding:utf-8
import cv2
import numpy as np
#先创建一个200*200的黑色空白图像
img = np.zeros((200, 200), dtype=np.uint8)
#在图像中心放置一个白色方块
img[50:150, 50:150] = 255
ret, thresh = cv2.threshold(img, 127, 255, 0)
#调用findContours()函数对图像进行二值化操作
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
img = cv2.drawContours(color, contours, -1, (255,0,0), 2)
cv2.imshow("contours", color)
cv2.waitKey()
cv2.destroyAllWindows()
findContours()函数有三个参数:输入图像、层次类型和轮廓逼近方法,同时也有三个返回值:修改后的图像、图像轮廓以及它们的层次。使用轮廓来画出图像的彩色版本并将其显示出来。
findContours()函数会修改原图像,因此建议使用img.copy()对原图像进行拷贝来作为输入图像。
findContours()函数会返回一个层次树。cv2.RETR_TREE参数会得到图像中轮廓的整体层次结构,以此来建立轮廓之间的“关系“。如果只想得到最外面的轮廓,可使用cv2.RETR_EXTERNAL。这对消除包含在其他轮廓中的轮廓很有用(比如在大多数情况下不需要检测一个目标包含在另一个与之相同的目标里面)。