OpenCV3计算机视觉:Python实现 读书笔记-第三章

第三章

计算机视觉三种常用色彩空间:

  • 灰度色彩空间
  • BGR
  • HSV(Hue:色调,Saturation:饱和度,Value:明亮程度)

使用函数cv2.imread(filepath,flags)读入一图片

  • filepath:要读入图片的完整路径
  • flags:读入图片的标志
    • cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道
    • cv2.IMREAD_GRAYSCALE:读入灰度图片(0)
    • cv2.IMREAD_UNCHANGED:读入完整图片,包括alpha通道

高通滤波器

  • 根据像素与邻近像素的亮度差值提升该像素的亮度
import cv2
import  numpy as np
from scipy import ndimage

kernal_3x3 = np.array( #卷积核(卷积矩阵,奇数行,列)
    [[-1,-1,-1],
     [-1,8,-1],
     [-1,-1,-1]
    ])

kernal_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("3_1.jpg",0)

k3 = ndimage.convolve( img , kernal_3x3 ) #卷积
k5 = ndimage.convolve( img , kernal_5x5 )

#GaussianBlur:用高斯滤波器(GaussianFilter)对图像进行平滑处理,将源图像与指定的高斯内核进行卷积
blurred = cv2.GaussianBlur( img , (11,11) , 0 )
g_hpf = img - blurred

cv2.imshow("3x3",k3)
cv2.imshow("5x5",k5)
cv2.imshow("g_hpf",g_hpf)
cv2.waitKey()
cv2.destroyAllWindows()

低通滤波器

  • 在像素与周围像素的亮度差值小于一个特定值时,平滑该像素的亮度
  • 主要用于去噪和模糊化(高斯模糊是最常用的模糊滤波器(平滑滤波器)之一,是一个削弱高频信号强度的低通滤波器)

边缘检测

OpenCV提供的边缘检测滤波函数
  • Laplacian()
  • Sobel()
  • Scharr()

这些滤波函数将非边缘区域转为黑色,边缘区域转为白色或者其他饱和的颜色。但容易将噪声识别为边缘,解决方法是在找到边缘之前对图像进行模糊处理

OpenCV提供的模糊滤波函数
  • blur():简单的算术平均
  • medianBlur():去除数字化的视频噪声非常有效,特别是去除彩色图像的噪声
  • GaussianBlur()
import cv2
import  numpy
import utils

def strokeEdges( src , blurKsize = 7 , edgeKsize = 5 ):
    if blurKsize >= 3:
        blurredSrc = cv2.medianBlur(src,blurKsize)
        graySrc = cv2.cvtColor(blurredSrc,cv2.COLOR_BGR2GRAY)
    else :
        graySrc = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
    cv2.Laplacian(graySrc,cv2.CV_8U,graySrc,ksize=edgeKsize)
    normalizedInverseAlpha = (1.0 / 255) * ( 255 - graySrc )
    channels = cv2.split(src)
    for channel in channels:
        channel[:] = channel * normalizedInverseAlpha
    cv2.merge(channels,dst)
用定制内核做卷积
  • 卷积矩阵:奇数行,奇数列的二维矩阵,中心元素对应于感兴趣像素,其他元素对应于这个像素周围邻近像素,每个元素都有一个整数或浮点数值,就是应用在像素值上的权重
kernal_3x3 = np.array( #卷积核
    [[-1,-1,-1],
     [-1,8,-1],
     [-1,-1,-1]
    ])

此3x3卷积矩阵表示感兴趣像素权重为8,邻近像素权重为-1。感兴趣像素的新像素是当前像素值*9,减去8个邻近像素值。若感兴趣像素与邻近像素有一点差别,则差别增加,图像锐化

  • OpenCV提供了通用的filter2D()函数,用户指定任意核
    cv2.filter2D(src,-1,kernal,dst)
    第二个参数指明目标图像每个通道的位深度(cv2.CV_8U表示每个通道为8位),若为负值,则表示目标图像和源图像位深度相同。
    • 对于彩色图像,filter2D()对每个通道都用相同的核,若要对每个通道使用不同的核,必须用split()和merge()函数
Canny边缘检测

算法过程:

  • 高斯滤波器对图像去噪
  • 计算梯度
  • 在边缘使用非最大抑制(NMS)
  • 在检测的边缘上使用双阈值去除假阳性
  • 分析所有边缘及其之间的连接

在OpenCV中一行代码就能实现:cv2.Canny(img,threshold1,threshold2)

  • threshold2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的threshold1用于将这些间断的边缘连接起来。
  • 返回一个二值图像,包含的是检测出来的边缘
import cv2
import numpy as np

img = cv2.imread("3_1.jpg",0)
cv2.imwrite("canny.jpg",cv2.Canny(img,200,300))
cv2.imshow("canny",cv2.imread("canny.jpg"))
cv2.waitKey()
cv2.destroyAllWindows()
轮廓检测

与其相关的操作:检测图像视频帧中物体轮廓,计算多边形边界,形状逼近,计算感兴趣区域

下例检测出正方形轮廓,并用绿色画出

import cv2
import numpy as np
#黑色空白图像200*200
img = np.zeros( ( 200 , 200 ) , dtype = np.uint8 )
#中央放置一个白色方块(np数组在切片上的赋值)
img[50:150, 50:150] = 255

"""
cv2.threshold(src, thresh, maxval, type) → retval, dst
src:表示的是图片源
thresh:表示的是阈值(起始值)
maxval:表示的是最大值
type:表示的是这里划分的时候使用的是什么类型的算法,常用值为0(cv2.THRESH_BINARY)
返回 阈值 和 处理后图像
"""
ret , thresh = cv2.threshold( img , 127 , 255 , 0 ) # 二值化(黑白)操作 , 0 :(cv2.THRESH_BINARY)

"""
findContours():
参数:输入图像,层次类型,轮廓逼近方法
"""
# 图像的轮廓,层次
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 , (0,255,0) , 2 )
cv2.imshow("contours" , color)
cv2.waitKey()
cv2.destroyAllWindows()
边界框,最小矩形区域,最小闭圆区域

加载图像,在源图像基础上二值化操作
在灰度图像上执行所有计算轮廓的操作,在源图像上利用色彩信息画这些轮廓

import cv2
import numpy as np

img = cv2.pyrDown(cv2.imread("3_3.png",cv2.IMREAD_UNCHANGED)) #图像降采样,对图像缩小

ret , thresh = cv2.threshold(cv2.cvtColor(img.copy(),cv2.COLOR_BGR2GRAY),127,255,cv2.THRESH_BINARY)

contours , hier = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

for c in contours:
    # find bounding box coordinates
    x , y , w , h = cv2.boundingRect(c)
    cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

    # find minimum area
    rect = cv2.minAreaRect(c)
    # calculate coordinates of the minimum area rectangle
    box = cv2.boxPoints(rect)
    # normalize coordinates to integers
    box = np.int0(box)
    # draw contours
    cv2.drawContours( img , [box] , 0 , (0,0,255) , 3 )
    # 第二个参数接收一个保存着轮廓的数组,[box]将box这组点放入数组中
	# 第三个参数是要绘制的轮廓数组的索引,-1表示绘制所有轮廓,否则只绘制轮廓数组里的轮廓

    (x,y),radius = cv2.minEnclosingCircle(c)
    # cast to integers
    center = (int(x),int(y))
    radius = int(radius)
    # draw the circle
    img = cv2.circle( img , center , radius , (0,255,0),2)

cv2.drawContours( img , contours , -1 , (255,0,0) , 1)
cv2.imshow("contours",img)
cv2.waitKey()
凸轮廓与Douglas-Peucker算法
  • 凸形状内任意两点的连线都在该形状里面

cv2.approxPolyDP 计算近似的多边形框

  • 第一个参数为轮廓
  • 第二个参数epsilon为源轮廓与近似多边形的最大差值(越小与轮廓越接近)
    • 计算轮廓周长 cv2.arclength(cnt,True) cnt为一个轮廓
    • epsilon 可取轮廓的1%,如:
    epsilon = 0.01 * cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt,epsilon,True)
    
  • 第三个参数为bool标记,表示多边形是否闭合
直线检测
import cv2
import numpy as np

img = cv2.imread('3_3.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,120) # Canny处理的单通道二值图像

minLineLength = 20 # 最小直线长度
maxLineGap = 5     # 最大线段间隙

#需要处理的图像,线段的几何表示(1 , np.pi/180 , 阈值),返回numpy.ndarray(N维数组对象,用于存放同类型元素的多维数组)
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
print(type(lines))
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()
圆检测
import cv2
import numpy as np

planets = cv2.imread('3_3.png')
gray = cv2.cvtColor(planets,cv2.COLOR_BGR2GRAY)
img = cv2.medianBlur(gray,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,255,0),3)
cv2.imshow("planets_circles",planets)

cv2.waitKey()
cv2.destroyAllWindows()

猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/104929413