赞
踩
按照OpenCV官方doc顺序来进行学习回忆和总结,本次的内容是opencv中的图像处理核心技术(imgproc.hpp),包括
图像处理常用的颜色空间有RGB、HSV、YCbCr、GRAY等
使用cv2.cvtColor(img, type)进行颜色空间的转换,需要注意的是imread默认读取图片为BGR
import cv2
import numpy as np
if __name__ == '__main__':
img = cv2.imread('starry_night.png')
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('img', img)
cv2.imshow('img_hsv', img_hsv)
cv2.imshow('img_gray', img_gray)
cv2.waitKey(0)
使用cv2.threshold()进行图像二值化,
需要注意,src必须是单通道图,thresh是阈值,二值化后像素值为{0, maxval},常用的type有
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_OTSU
# ret, dst = cv2.threshold(src, thresh, maxval, type)
cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY)
此外,还有自适应阈值二值化方法,
# cv2.adaptiveThreshold(src, maxval, method, type, blocksize, C)
dst = cv2.adaptiveThreshold(src, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 3, 10)
blocksize是分割计算的区域大小,必须是奇数
C表示每个区域计算出阈值后,减去这个常数作为这个区域的最终阈值
使用cv2.inRange()进行颜色阈值筛选,其中lowerthres和upperthres分别表示长度与图片通道数相同的阈值数组
# mask = cv2.inRange(img, lowerthres, upperthres)
mask = cv2.inRange(img_hsv, np.array([100, 40, 40]), np.array([120, 240, 240]))
输入RGB:
转到HSV空间:
HSV空间颜色提取:
常用的图像滤波方法包括均值滤波,中值滤波,高斯滤波,双边滤波等
均值滤波将中心附近像素累计平均后作为中心值,滤波后图像变模糊
中值滤波取中心附近像素值的中值,适合去除椒盐噪声
高斯滤波采用高斯核进行加权平均,适合去除高斯噪声
双边滤波在滤波时能保持边缘的清晰度
# 均值滤波cv2.blur(img, Ksize)
img_blur = cv2.blur(img, (3, 3))
# 中值滤波cv2.medianBlur(img, Ksize)
img_median_blur = cv2.medianBlur(img, 3)
# 高斯滤波cv2.GaussianBlur(img, Ksize, Sigma)
img_gauss_blur = cv2.GaussianBlur(img, (3, 3), 0)
# 双边滤波cv2.bilateralFilter(img, d, sigmaColor, sigmaSpace)
img_bliteral_blur = cv2.bilateralFilter(img, 9, 20, 45)
在图像处理,如二值化、颜色筛选后,目标图案被截断需要截断时,可以通过形态学操作进行填充和削减
主要针对二值图像,腐蚀是将图像中黑色区域进一步“吞噬”白色区域,膨胀则是让白色区域“吞噬”黑色区域。
在形态学操作前,首先要获得“吞噬”的模板,即核的形状,可选的形状有
cv2.MORPH_RECT
cv2.MORPH_CROSS
cv2.MORPH_ELLIPSE
也可以通过numpy数组自定义核形状
# 获得核 cv2.getStructuringElement(type, Ksize)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# or 自定义核形状
kernel_np = np.ones([3, 3], np.uint8)
# 腐蚀 cv2.erode(img, kernel, iterations=None)
img_erode = cv2.erode(img, kernel)
# 膨胀 cv2.dilate(img, kernel)
img_dilate = cv2.dilate(img, kernel)
先腐蚀将图像中相连的部分截断,再膨胀的操作是开运算
先膨胀将图像中断开的部分连接,再腐蚀的操作是闭运算
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 开运算
img_open = cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel)
# 闭运算
img_close = cv2.morphologyEx(src, cv2.MORPH_CLOSE, kernel)
传统边缘检测算法主要采用一阶微分算子Sobel,Roberts,Prewitt等以及二阶算子Canny,Laplace等
def edge_Sobel(img):
# Sobel 算子
x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)
# 转 uint8 ,图像融合
X = cv2.convertScaleAbs(x)
Y = cv2.convertScaleAbs(y)
img_sobel = cv2.addWeighted(X, 0.5, Y, 0.5, 0)
return img_sobel
def edge_Roberts(img):
# Roberts 算子
kernelx = np.array([[-1, 0], [0, 1]], dtype=int)
kernely = np.array([[0, -1], [1, 0]], dtype=int)
x = cv2.filter2D(img, cv2.CV_16S, kernelx)
y = cv2.filter2D(img, cv2.CV_16S, kernely)
X = cv2.convertScaleAbs(x)
Y = cv2.convertScaleAbs(y)
img_roberts = cv2.addWeighted(X, 0.5, Y, 0.5, 0)
return img_roberts
def edge_Prewitt(img):
# Prewitt 算子
kernelx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]], dtype=int)
kernely = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=int)
x = cv2.filter2D(img, cv2.CV_16S, kernelx)
y = cv2.filter2D(img, cv2.CV_16S, kernely)
# 转 uint8 ,图像融合
X = cv2.convertScaleAbs(x)
Y = cv2.convertScaleAbs(y)
img_prewitt = cv2.addWeighted(X, 0.5, Y, 0.5, 0)
return img_prewitt
def edge_canny(img):
# Canny
dst = cv2.Canny(img, 45, 90)
img_canny = dst
return img_canny
def edge_laplace(img):
# Laplacian
dst = cv2.Laplacian(img, cv2.CV_16S, ksize=3)
img_laplace = cv2.convertScaleAbs(dst)
return img_laplace
import cv2 import numpy as np def edge_Roberts(img): # Roberts 算子 kernelx = np.array([[-1, 0], [0, 1]], dtype=int) kernely = np.array([[0, -1], [1, 0]], dtype=int) x = cv2.filter2D(img, cv2.CV_16S, kernelx) y = cv2.filter2D(img, cv2.CV_16S, kernely) X = cv2.convertScaleAbs(x) Y = cv2.convertScaleAbs(y) img_roberts = cv2.addWeighted(X, 0.5, Y, 0.5, 0) return img_roberts def edge_Prewitt(img): # Prewitt 算子 kernelx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]], dtype=int) kernely = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=int) x = cv2.filter2D(img, cv2.CV_16S, kernelx) y = cv2.filter2D(img, cv2.CV_16S, kernely) # 转 uint8 ,图像融合 X = cv2.convertScaleAbs(x) Y = cv2.convertScaleAbs(y) img_prewitt = cv2.addWeighted(X, 0.5, Y, 0.5, 0) return img_prewitt def edge_Sobel(img): # Sobel 算子 x = cv2.Sobel(img, cv2.CV_16S, 1, 0) y = cv2.Sobel(img, cv2.CV_16S, 0, 1) # 转 uint8 ,图像融合 X = cv2.convertScaleAbs(x) Y = cv2.convertScaleAbs(y) img_sobel = cv2.addWeighted(X, 0.5, Y, 0.5, 0) return img_sobel def edge_laplace(img): # Laplacian dst = cv2.Laplacian(img, cv2.CV_16S, ksize=3) img_laplace = cv2.convertScaleAbs(dst) return img_laplace def edge_canny(img): # Canny dst = cv2.Canny(img, 45, 90) img_canny = dst return img_canny if __name__ == "__main__": img = cv2.imread('distorted.png') img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, img_thres = cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY) img_thres = img_gray img_roberts = edge_Roberts(img_thres) img_prewitt = edge_Prewitt(img_thres) img_sobel = edge_Sobel(img_thres) img_laplace = edge_laplace(img_thres) img_canny = edge_canny(img_thres) cv2.imshow('img_roberts', img_roberts) cv2.imshow('img_prewitt', img_prewitt) cv2.imshow('img_sobel', img_sobel) cv2.imshow('img_laplace', img_laplace) cv2.imshow('img_canny', img_canny) cv2.waitKey(0)
输入:
Roberts:
Prewitt:
Sobel:
Laplace:
Canny:
本次总结回顾了OpenCV图像处理中的核心操作,包括颜色处理,滤波去噪,腐蚀膨胀开闭运算,边缘检测算子。下次将继续学习轮廓操作、霍夫变换和直方图操作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。