本文共 7890 字,大约阅读时间需要 26 分钟。
opencv常用函数和常用操作
https://blog.csdn.net/qq_45453266/article/details/106698699
读取图片,默认是三通道(BGR)的彩色图,flags=0读入灰度图
该函数有两个参数,第一个参数是图片的地址,第二个参数是读取图像的方式(默认值为1,以RGB格式读取)Flags指定了所读取图片的颜色类型
cv2.IMREAD_COLOR:加载彩色图片,这个是默认参数,可以直接写1。 cv2.IMREAD_GRAYSCALE:以灰度模式加载图片,可以直接写0。 cv2.IMREAD_UNCHANGED:包括alpha,可以直接写-1flags >0 返回3通道彩色图
注意:alpha 通道将被忽略,如果需要alpha 通道,请使用负值 =0 返回灰度图 <0 返回原图(带alpha 通道)显示图片,需与cv2.waitkey(0)一起使用,不然只显示一瞬间
以窗口的形式显示图片,两个参数,第一个是窗口上显示的名称,第二个是图像在代码中的表示名称N个参数,第一个是要保存的图像的名字,如 ‘Rachel.jpg’ ,
第二个是也是图像在代码中的表示名称,此外还有图像的质量等参数,暂且略过括号里填指定窗口名称
显示图片时间,单位为ms,0代表一直显示
缩放图片是非常常用的操作,cv2里面的函数是:cv2.resize
函数原型:cv2.resize(src, dst, dsize, fx=0, fy=0, interpolation=INTER_LINEAR )
fx,fy表示缩放比例,interpolation是缩放时填充的类型,有以下几种:
INTER_NEAREST(邻近元素插值法)
INTER_LINEAR(缺省值,双线性插值)
INTER_AREA(使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。当图像放大时,类似于 CV_INTER_NN 方法)
INTER_CUBIC(立方插值)
示例代码:
图片变成原图的0.5倍的灰度图
import cv2 img = cv2.imread('Rachel.jpg', 0) # 注意,第二个参数是0,灰度图new = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC)cv2.imshow('Rachel', new)k = cv2.waitKey(0)if k == ord('s'): cv2.imwrite('Rachel1.jpg', new) cv2.destroyAllWindows()
#只保留R通道为例 img[:,:,0]=0 #将B通道全部置为0 img[:,:,1]=0 #将R通道全部置为0
top,bottom,left,right分别表示在原图四周扩充边缘的大小
borderType:扩充边缘的类型,就是外插的类型,OpenCV中给出以下几种方式
p_top,p_bottom,p_left,p_right=(50,50,50,50) wrap=cv2.copyMakeBorder(img,p_top,p_bottom,p_left,p_right,cv2.BORDER_WRAP)
img = cv2.imread('1.png') img1 = cv2.imread('2.png') #!!!注意shape得出来的是(height,width),resize传入的是(width,height) h, w = img1.shape[:2] #将img的宽高转为img1的宽高 img = cv2.resize(img, (w, h)) #αX1+βX2+b img2 = cv2.addWeighted(img1, 0.4, img, 0.6, 0)
ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
cv2.THRESH_BINARY_INV THRESH_BINARY的反转
cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]for i in range(6): plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([])# 将生成画图保存为图片plt.savefig('1.jpg')plt.show()
原图
简单的平均卷积操作
blur = cv2.blur(img, (3, 3))cv2.imshow('blur', blur)cv2.waitKey(0)cv2.destroyAllWindows()
基本和均值一样,可以选择归一化
box = cv2.boxFilter(img,-1,(3,3), normalize=True) cv2.imshow('box', box)cv2.waitKey(0)cv2.destroyAllWindows()
基本和均值一样,可以选择归一化,容易越界
box = cv2.boxFilter(img,-1,(3,3), normalize=False) cv2.imshow('box', box)cv2.waitKey(0)cv2.destroyAllWindows()
高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)cv2.imshow('aussian', aussian)cv2.waitKey(0)cv2.destroyAllWindows()
相当于用中值代替
median = cv2.medianBlur(img, 5) # 中值滤波cv2.imshow('median', median)cv2.waitKey(0)cv2.destroyAllWindows()
kernel = np.ones((3, 3), np.uint8)# 腐蚀操作 img= cv2.erode(img, kernel, iterations=1)
kernel = np.ones((3, 3), np.uint8)img = cv2.dilate(img, kernel, 1)
img = cv2.imread('1.png', cv2.IMREAD_GRAYSCALE)img1 = cv2.Canny(img, 80, 150)#阈值越大,过滤掉的细节越多img2 = cv2.Canny(img, 20, 200)
img1 = cv2.pyrUp(img)
img2 = cv2.pyrDown(img)
拉普拉斯金字塔(原图-(先缩小后放大))
img3 = cv2.pyrUp(cv2.pyrDown(img))img.resize(img3.shape)img4 = img-img3
mode:轮廓检索模式
method:轮廓逼近方法
img = cv2.imread('1.png')# 转化为灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 使用二值图ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 根据灰度二值图找出轮廓contours, hierarchy = cv2.findContours( thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)# 画出轮廓# 这里要将原图copy一下,不然直接就在原图上画了img1 = img.copy()img2 = cv2.drawContours(img1, contours, -1, (0, 0, 255), 2)
img = cv2.imread('1.png')# 转化为灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 使用二值图ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 根据灰度二值图找出轮廓contours, hierarchy = cv2.findContours( thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)cnt = contours[0]# 普朗克算法epsilon = 0.1*lengthapprox = cv2.approxPolyDP(cnt, epsilon, True)img3 = img.copy()img4 = cv2.drawContours(img3, [approx], -1, (0, 0, 255), 2)
模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出。假如原图形是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1)
公式:
# 以灰度图方式读入img = cv2.imread('2.jpg',0)template = cv2.imread('1_template.png',0)h, w = template.shape[:2]# 可选的算法数组methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']for meth in methods: img2 = img.copy() # 匹配方法的真值 method = eval(meth) print (method) res = cv2.matchTemplate(img, template, method) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值 if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]: top_left = min_loc else: top_left = max_loc bottom_right = (top_left[0] + w, top_left[1] + h) # 画矩形 cv2.rectangle(img2, top_left, bottom_right, 255, 2) plt.subplot(121), plt.imshow(res, cmap='gray') plt.xticks([]), plt.yticks([]) # 隐藏坐标轴 plt.subplot(122), plt.imshow(img2, cmap='gray') plt.xticks([]), plt.yticks([]) plt.suptitle(meth) plt.show()
img_rgb = cv2.imread('mario.jpg')img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)template = cv2.imread('mario_coin.jpg', 0)h, w = template.shape[:2]res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)threshold = 0.8# 取匹配程度大于%80的坐标loc = np.where(res >= threshold)for pt in zip(*loc[::-1]): # *号表示可选参数 bottom_right = (pt[0] + w, pt[1] + h) cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)cv2.imshow('img_rgb', img_rgb)cv2.waitKey(0)
img = cv2.imread('cat.jpg',0) #0表示灰度图hist = cv2.calcHist([img],[0],None,[256],[0,256])hist.shapeplt.hist(img.ravel(),256); plt.show()