def gradientTest2(): img = cv2.imread("./images/pie.png") kernel = np.ones((7, 7), np.uint8) # 计算梯度 gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) cv_show(gradientTest())
def topHatTest(): # 顶帽 = 原始输入 - 开运算结果 # 只有细节信息 img = cv2.imread("./images/dige.png") kernel = np.ones((7, 7), np.uint8) topHat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) cv_show(topHat)
def scharrAndLaplacianTest(): """ 图像梯度: Scharr算子: 比sobel算子更精细, Gx = [[-3, 0, 3], [-10, 0, 10], [-3, 0, 3]] Gy = [[-3, -10, -3], [0, 0, 0], [-3, -10, -3]] laplacian算子: 二阶导,对变化更明显, 但是对噪音敏感 G = [[0, 1, 0], [1, -4, 1], [0, 1, 0]] :return: """ # img = cv2.imread("./images/pie.png", cv2.IMREAD_GRAYSCALE) img = cv2.imread("./images/lena.jpg", cv2.IMREAD_GRAYSCALE) sobelX = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) sobelX = cv2.convertScaleAbs(sobelX) sobelY = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) sobelY = cv2.convertScaleAbs(sobelY) sobelXY = cv2.addWeighted(sobelX, 0.5, sobelY, 0.5, 0) scharrX = cv2.Scharr(img, cv2.CV_64F, 1, 0) scharrY = cv2.Scharr(img, cv2.CV_64F, 0, 1) scharrX = cv2.convertScaleAbs(scharrX) scharrY = cv2.convertScaleAbs(scharrY) scharrXY = cv2.addWeighted(scharrX, 0.5, scharrY, 0.5, 0) laplacian = cv2.Laplacian(img, cv2.CV_64F) laplacian = cv2.convertScaleAbs(laplacian) res = np.hstack((sobelXY, scharrXY, laplacian)) cv_show(res)
def blackHatTest(): # 黑帽 = 闭运算 - 原始输入 # 原始的小轮廓 img = cv2.imread("./images/dige.png") kernel = np.ones((7, 7), np.uint8) blackHat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) cv_show(blackHat)
def smoothOperationTest(): # 带有椒盐噪声的图像 img = cv2.imread("./images/lenaNoise.png") print(img.shape) # cv_show(img) # 均值滤波 # 简单的平均卷积操作 blur = cv2.blur(img, (3, 3)) # 方框滤波 # 可以选择是否归一化,归一化就跟均值滤波一摸一样,不归一化 相加后最大值为255 box = cv2.boxFilter(img, -1, (3, 3), normalize=True) # box = cv2.boxFilter(img, -1, (3, 3), normalize=False) # cv_show(box) # 高斯滤波 # 高斯滤波的卷积核里的数值时满足高斯分布,相当于更重视中间的 aussian = cv2.GaussianBlur(img, (5, 5), 1) # cv_show(aussian) # 中值滤波 # 对卷积核中的数值进行排序,取中间的值取代 median = cv2.medianBlur(img, 5) # cv_show(median) # 展示所有 res = np.hstack((blur, aussian, median)) cv_show(res)
def dilateTest(): img = cv2.imread("./images/dige.png") print(img.shape) # cv_show(img) kernel = np.ones((3, 3), np.uint8) erosion = cv2.erode(img, kernel, iterations=1) dige_dilate = cv2.dilate(erosion, kernel, iterations=1) # 白色被放大 cv_show(dige_dilate)
def openMorphTest(): # 开运算: 先腐蚀,再膨胀 # 没有胡须 img = cv2.imread("./images/dige.png") kernel = np.ones((5, 5), np.uint8) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) cv_show(opening)
def erodeTest(): img = cv2.imread("./images/dige.png") print(img.shape) # cv_show(img) kernel = np.ones((5, 5), np.uint8) # 总共有两个参数: kernel 和 循环次数; # 腐蚀会使白色变小 erosion = cv2.erode(img, kernel, iterations=1) # 白字变细了, 胡须没有了 cv_show(erosion)
def erodeTest2(): img = cv2.imread("./images/pie.png") print(img.shape) # cv_show(img) kernel = np.ones((30, 30), np.uint8) erosion_1 = cv2.erode(img, kernel, iterations=1) erosion_2 = cv2.erode(img, kernel, iterations=2) erosion_3 = cv2.erode(img, kernel, iterations=3) res = np.hstack((erosion_1, erosion_2, erosion_3)) cv_show(res)
def dilateTest2(): img = cv2.imread("./images/pie.png") print(img.shape) # cv_show(img) kernel = np.ones((30, 30), np.uint8) dilate_1 = cv2.dilate(img, kernel, iterations=1) dilate_2 = cv2.dilate(img, kernel, iterations=2) dilate_3 = cv2.dilate(img, kernel, iterations=3) res = np.hstack((dilate_1, dilate_2, dilate_3)) cv_show(res)
def closeMorphTest(): # 闭运算: 先膨胀,再腐蚀 # 膨胀后 胡须变大,再腐蚀,就会腐蚀失败 img = cv2.imread("./images/dige.png") kernel = np.ones((5, 5), np.uint8) closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) cv_show(closing)
def gradientTest(): # 梯度 = 膨胀 - 腐蚀 img = cv2.imread("./images/pie.png") kernel = np.ones((7, 7), np.uint8) # 膨胀 dilate = cv2.dilate(img, kernel, iterations=1) # 腐蚀 erosion = cv2.erode(img, kernel, iterations=1) res = np.hstack((dilate, erosion)) gradient = cv2.subtract(dilate, erosion) cv_show(gradient)
def laplasPyramidTest(): """ 拉普拉斯金字塔: Li = Gi - PyrUp(PyrDown(Gi)) # G(i+1) = pyrDown(Gi) 1.低通滤波 2.缩小尺寸 3. 放大尺寸 4. 图像相减 :return: """ img = cv2.imread("./images/AM.png") down = cv2.pyrDown(img) downUp = cv2.pyrUp(down) G = img - downUp cv_show(G)
def contourTemplateMultiMatchTest(): # 匹配多个对象 img = cv2.imread("./images/lena.jpg", 0) template = cv2.imread("./images/lena_face.jpg", 0) print(img.shape) print(template.shape) h, w = template.shape[:2] res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED) threshold = 0.8 # 取匹配程度大于0.8的坐标 loc = np.where(res >= threshold) for pt in zip(*loc[::-1]): # *号表示可选参数 bottom_right = (pt[0] + w, pt[1] + h) cv2.rectangle(img, pt, bottom_right, (0, 0, 255), 2) cv_show(img)
def harrisTest(): """ cv2.cornerHarris() img: 数据类型为float32的输入图像 blockSize: 角点检测中指定区域的大小 ksize: Sobel求导中使用的窗口大小, 一般为3 k: 取值参数为[0.04, 0.06], 一般为0.04 """ # img = cv2.imread("./images/chessboard.jpg") img = cv2.imread("./images/test_1.jpg") print("img shape:{}".format(img.shape)) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # grapy = np.float32(gray) # uint8 -> float32 dst = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04) print("dst shape:{}".format( dst.shape)) # 输出的是 每个点出的 值,故维度为(height, widith) img[dst > 0.01 * dst.max()] = [0, 0, 255] # 将最大值的k倍, 将点标记为红色 cv_show(img)
def siftTest(): img = cv2.imread("./images/test_1.jpg") # img = cv2.imread("./images/lena.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 得到特征点 # 构造sift实例 sift = cv2.xfeatures2d.SIFT_create() # 获取关键点 kp = sift.detect(gray, None) # 画出关键点 img = cv2.drawKeypoints(gray, kp, img) cv_show(img) # 计算特征 kp, des = sift.compute(gray, kp) print(np.array(kp).shape) # 关键点的坐标 (6827,) print(des.shape) # (6827,128) 关键点对应的向量,向量维度是 128,
def sobelTest(): """ sobel算子, 这里是X方向的算子, 右-左 Gx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]] Y方向的算子, 下 - 上 Gy = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]] dst = cv2.Sobel(src, ddepth, dx, dy, ksize) ddepth: 图像的深度 dx和dy分别表示水平和竖直方向; 可以单独计算也可以一起计算,建议分开计算再合并 ksize是Sobel算子的大小 """ # img = cv2.imread("./images/pie.png", cv2.IMREAD_GRAYSCALE) img = cv2.imread("./images/lena.jpg", cv2.IMREAD_GRAYSCALE) # cv_show(img) # 先计算X方向 # 白到黑是正数,黑到白是负数,所有的负数会被截断成0, 索要要取绝对值 # cv2.CV_64F 能表示负数 sobelX = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) # cv_show(sobelX) sobelX = cv2.convertScaleAbs(sobelX) # 但是上面会缺失 # cv_show(sobelX) # 再计算Y方向 sobelY = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) sobelY = cv2.convertScaleAbs(sobelY) # cv_show(sobelY) # 将X和Y方向合并 sobelXY = cv2.addWeighted(sobelX, 0.5, sobelY, 0.5, 0) cv_show(sobelXY) # 直接一起计算 # 有重影,实际用的时候不建议一起计算 sobelXYTogether = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3) sobelXYTogether = cv2.convertScaleAbs(sobelXYTogether)
def gaosiPyramidTest(): """ 图像金字塔分为:高斯金字塔和拉普拉斯金字塔 图像金字塔表示:同一张图像,按照不同比例进行缩放不同的大小,组合在一起就是图像金字塔 图像金字塔的操作分为两种:向下采样(缩小)和向上采样(放大) 高斯金字塔:向下采样方法(缩小) Gkernel = 1/16 *[ [1, 4, 6, 4, 1], [4, 16, 24, 16, 4], [6, 24, 36, 24, 6], [4, 16, 24, 16, 4], [1, 4, 6, 4, 1]] 1.将G与高斯内核卷积,2.将所有偶数行和列去除 高斯金字塔:向上采样方法(放大) [[10, 30],[56, 96]] -> [[10, 0, 30, 0],[0, 0, 0, 0],[56, 0, 96, 0], [0, 0, 0, 0]] 1.将图像在每个方向扩大为原来的两倍,新增的行和列以0填充 2.使用先前同样的内核(乘以4)与放大后的图像卷积,获得近似值 """ img = cv2.imread("./images/AM.png") # cv_show(img) print("origin shape:{}".format(img.shape)) up = cv2.pyrUp(img) print("up shape:{}".format(up.shape)) # cv_show(up) down = cv2.pyrDown(img) # 下采样损失很多信息 print("down shape:{}".format(down.shape)) # cv_show(down) up2 = cv2.pyrUp(img) print("up2 shape:{}".format(up2.shape)) # cv_show(up2) down2 = cv2.pyrDown(down) print("down2 shape:{}".format(down2.shape)) # cv_show(down2) upDown = cv2.pyrDown(up) print("upDown shape:{}".format(upDown.shape)) cv_show(upDown) downUp = cv2.pyrUp(down) # 还原回来很模糊, 下采样损失很多信息 print("downUp shape:{}".format(downUp.shape)) cv_show(downUp)
def siftFeatureMatchTest(): smallImg = cv2.imread("./images/box.png", 0) img = cv2.imread("./images/box_in_scene.png", 0) cv_show(smallImg) cv_show(img) # 构建sift实例 sift = cv2.xfeatures2d.SIFT_create() # 计算关键点和点对应向量 kp1, des1 = sift.detectAndCompute(smallImg, None) kp2, des2 = sift.detectAndCompute(img, None) # 暴力匹配 # crossCheck表示两个特征要相互匹配, # 例如A中的第i点的特征与B中的第j点的特征最近,并且B中的第j个特征点到A中第i个特征点也是最近滴 bf = cv2.BFMatcher(crossCheck=True) matches = bf.match(des1, des2) matches = sorted(matches, key=lambda x: x.distance) img3 = cv2.drawMatches(smallImg, kp1, img, kp2, matches[:10], None, flags=2) cv_show(img3) # K对最佳匹配 bf2 = cv2.BFMatcher() matchesK = bf2.knnMatch(des1, des2, k=2) good = [] for m, n in matchesK: if m.distance < 0.75 * n.distance: good.append([m]) img3 = cv2.drawMatchesKnn(smallImg, kp1, img, kp2, good[:10], None, flags=2) cv_show(img3)
from imageJoint.Stitcher import Stitcher import cv2 from cvBaseOperation import cv_show # 读取拼接图片 imageA = cv2.imread("./images/left_01.png") imageB = cv2.imread("./images/right_01.png") cv_show(imageA, "Image A") cv_show(imageB, "Image B") # 把图片拼接成全景图 stitcher = Stitcher() (result, vis) = stitcher.stitch([imageA, imageB], showMatches=True) # 显示所有图片 cv_show(vis, "Keypoint Matches") cv_show(result, "Result")
def contourTest(): """ 边缘与轮廓的区别: 边缘可以是线段零零散散的,轮廓必须连接在一起整体; cv2.findContours(img, mode, method) mode: 轮廓检索模式 RETR_EXTERNAL: 只检索最外面的轮廓; RETR_LIST: 检索所有的轮廓,并将其保存到一个链表中 RETR_CCOMP: 检索所有的轮廓,并将他们组织为两层,顶层是各部分的外部边界,第二层是空洞的边界; RETR_TREE: 检索所有的轮廓,并重构嵌套轮廓的整个层次;--一般填这个 method: 轮廓逼近方法 CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他的方法输出多边形(顶点的序列) CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。 """ # img = cv2.imread("./images/contours2.png") img = cv2.imread("./images/contours.png") # img = cv2.imread("./images/car.png") # 为了更高的准确率,使用二值图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # cv_show(thresh, "thresh") binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # binary跟输入的thresh一模一样, # contours是一个列表,表示检测的结果 # hierarchy 层级 # 绘制轮廓 # 传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度 # 注意需要copy, 要不原图会变 draw_img = img.copy() # draw_img = thresh.copy() # 灰度图看不清 res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2) # cv_show(res) # 计算轮廓的面积和周长 index = 0 cnt = contours[index] area = cv2.contourArea(cnt) # True: 表示闭合的 arcLen = cv2.arcLength(cnt, True) print("index:{} area:{} 周长:{}".format(index, area, arcLen)) # 轮廓近似 epsilon = 0.2 * cv2.arcLength(cnt, True) # 阈值用 周长的0.1,可以变 approx = cv2.approxPolyDP(cnt, epsilon, True) draw_img2 = img.copy() res2 = cv2.drawContours(draw_img2, [approx], -1, (0, 0, 255), 2) # cv_show(res2) # 边界矩形 x, y, w, h = cv2.boundingRect(cnt) imgRect = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) rectArea = w * h extent = float(area) / float(rectArea) print("轮廓面积与边界矩形比:{}".format(extent)) # cv_show(imgRect) # 边界圆 (x, y), radius = cv2.minEnclosingCircle(cnt) center = (int(x), int(y)) radius = int(radius) imgCircle = cv2.circle(img, center, radius, (0, 255, 0), 2) cv_show(imgCircle)