计算机视觉三种常用色彩空间:
使用函数cv2.imread(filepath,flags)读入一图片
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()
这些滤波函数将非边缘区域转为黑色,边缘区域转为白色或者其他饱和的颜色。但容易将噪声识别为边缘,解决方法是在找到边缘之前对图像进行模糊处理
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个邻近像素值。若感兴趣像素与邻近像素有一点差别,则差别增加,图像锐化
。
filter2D()
函数,用户指定任意核cv2.filter2D(src,-1,kernal,dst)
filter2D()
对每个通道都用相同的核,若要对每个通道使用不同的核,必须用split()和merge()函数
算法过程:
在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()
cv2.approxPolyDP
计算近似的多边形框
epsilon
为源轮廓与近似多边形的最大差值(越小与轮廓越接近)
cv2.arclength(cnt,True)
cnt
为一个轮廓epsilon
可取轮廓的1%,如:epsilon = 0.01 * cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
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()