OpenCV3 处理图像
1 不同色彩空间的转化(灰度 BGR HSV)
2 傅里叶变换
认为观察到的所有波形都是由一系列简单的且频率不同的正弦曲线叠加得到的
应用: 高通滤波器 (根据像素与临近像素的亮度差值来提升该像素亮度)
低通滤波器(平滑像素的亮度,主要用于去噪和模糊化 比如:高斯模糊)
3 边缘检测
调用拉普拉斯函数
#本函数功能进行图片边缘的增强
def strokeEdges(src, dst, blurKsize = 7, edgeKsize = 5):
#利用medianBlur 作为模糊函数 去除图像的噪声
#使用 Laplacian 函数作为边缘检测函数 使产生明显的线条
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) #将通道进行合并
卷积滤波器
class VConvolutionFilter(object):
def __init__(self, kernel):
self._kernel = kernel
def apply(self, src, dst):
cv2.filter2D(src, -1, self._kernel, dst)
class SharpenFilter(VConvolutionFilter):
# 锐化滤波器
def __init__(self):
kernel = numpy.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
# 不想改变图像的亮度,核的权重为1
# 稍微修改一下权重 使他的权重为0 就会得到一个边缘检测核
super(SharpenFilter).__init__(kernel)
class BlurFilter(VConvolutionFilter):
def __init__(self):
kernel = numpy.array([[0.4, 0.4, 0.4, 0.4, 0.4],
[0.4, 0.4, 0.4, 0.4, 0.4],
[0.4, 0.4, 0.4, 0.4, 0.4],
[0.4, 0.4, 0.4, 0.4, 0.4],
[0.4, 0.4, 0.4, 0.4, 0.4]] )
super(SharpenFilter).__init__(kernel)
Canny边缘检测
Canny边缘检测算法有五个步骤:
高斯滤波器对图像进行去噪、
计算梯度、
在边缘上使用非最大抑制、
在检测到的边缘上使用双阈值去除假阳性、最后分析所有边缘以及其之间的所有连接
import cv2
import numpy as np
img = cv2.imread("D:\\PostgraduateStudy\\ComputerVision\\src\\pic\\01.PNG")
cv2.imwrite("canny.jpg", cv2.Canny(img, 200, 300))
cv2.imshow("canny", cv2.imread("canny.jpg"))
cv2.waitKey()
cv2.destoryAllWindows()
轮廓检测
import cv2
import numpy as np
img = np.zeros((200, 200), dtype=np.uint8)
img[50:150, 50:150] = 255
ret, thresh = cv2.threshold(img, 127, 255, 1)
# 二值化函数 返回ret阈值 以及像素矩阵# THRESH_BINARY 像素值大于阈值时,取Maxval,否则取0contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# img , mode, method 输入图像 层次类型 轮廓逼近方法
# mode: cv2.RETR_TREE:以树形结构输出轮廓信息。
# method: cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标;
# contours:list结构,列表中每个元素代表一个边沿信息。每个元素是(x,1,2)的三维向量,
# x表示该条边沿里共有多少个像素点,第三维的那个“2”表示每个点的横、纵坐标;#hierarchy表示层次color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)img = cv2.drawContours(color, contours, -1, (0, 255, 0), 2)
#第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓,
#第四个参数color为轮廓的颜色,
#第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,
cv2.imshow("contours", img)
cv2.waitKey()
cv2.destroyAllWindows()
边界框 最小矩形区域 最小闭圆的轮廓
import cv2
import numpy as np
img = cv2.pyrDown(cv2.imread("D:\\PostgraduateStudy\\ComputerVision\\src\\pic\\hammer.PNG", cv2.IMREAD_UNCHANGED))
# 对图像先进行高斯平滑,再进行下采样
# IMREAD_UNCHANGED 以原先的方式打开图像 彩色就是彩色 灰度就是灰度
ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY),
127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh,
cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# img mode method mode:cv2.RETR_EXTERNAL表示只检测外轮廓
for c in contours:
#找边界的坐标
x, y, w, h = cv2.boundingRect(c)
#根据边界坐标绘制一个简单的矩形
cv2.rectangle(img, (x,y), (x+w, y+h), (0, 255, 0), 2)
# #计算出包围目标的最小矩形区域
# rect = cv2.minAreaRect(c)
# box = cv2.boxPoints(rect)
# box = np.int0(box)#将坐标转换为整型
# cv2.drawContours(img, [box], 0, (0, 0, 255), 3)
(x, y), radius = cv2.minEnclosingCircle(c)
center = (int(x), int(y))
radius = int(radius)
img = cv2.circle(img, center, radius, (0, 255, 0), 1)
cv2.drawContours(img, contours, -1, (255, 0, 0), 1)
cv2.imshow("contours", img)
cv2.waitKey(0)
4 直线检测 与圆检测
import cv2
import numpy as np
import math
#检测直线
img = cv2.imread("lines.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 120)
minLineLength = 20
maxLineGap = 5
lines = cv2.HoughLinesP(edges, 1, math.pi/180, 100, minLineLength,
maxLineGap)
# 直线检测函数
#src(dst): 边缘检测的输出图像.它应该是个灰度图(但事实上是个二值化图)
#lines: 储存着检测到的直线的参数对(r,\theta) 的容器 * rho: 参数极径r以像素值为单位的分辨率.我们使用1像素
#theta: 参数极角 \theta以弧度为单位的分辨率.我们使用1度(即CV_PI / 180)
#threshold: 要”检测” 一条直线所需最少的的曲线交点
#srn and stn: 参数默认为0.查缺OpenCV参考文献来获取更多信息.
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("D:\\PostgraduateStudy\\ComputerVision\\src\\pic\\hammer.PNG")
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)
# inputarray 输入图像 outputarray 存储检测到的圆的输出矢量
# method 检测的方法, 霍夫梯度法
# 用来检测圆心累加器图像分辨率与输入图像之比的倒数 dp 为1则累加器与输入图像具有相同的分辨率
#param1:它是第三个参数method设置的检测方法的对应的参数。
# 对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
#param2:也是第三个参数method设置的检测方法的对应的参数,对当前唯一的方法霍夫梯度法HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。
# 它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
circles = np.uint16(np.around(circles))
#print(circles)
#print(circles.ndim)
# 3 维数组 即有a个batch 每个batch有b 个通道 每个通道大小为c
# 在这里 有 1个 batch 每个batch 15个通道 每个通道大小是3
for i in circles[0, :]:
#第0 batch内所有的所有通道的所有元素
# 画⚪
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("pla.jpg", planets)
cv2.imshow("", planets)
print("hhhh")
cv2.waitKey()
cv2.destroyAllWindows()