opencv图像处理-从傅里叶变换开始

1、傅里叶变换

1)nunpy中的操作

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('opencv/data/messi5.jpg', 0)
#二维傅里叶变换,转换成频率的函数,频率变化大的部位绝对值高
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# 这里构建振幅图的公式,一个y轴对称在正向递增的变换
magnitude_spectrum = 20 * np.log(np.abs(fshift))

rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)
#原图中央白亮,代表低频成分,将其设置为0,消除低频成分,相当于找轮廓
fshift[crow - 30:crow + 30, ccol - 30:ccol + 30] = 0
f_ishift = np.fft.ifftshift(fshift)  #逆平移
img_back = np.fft.ifft2(f_ishift)   #逆傅里叶变换
img_back = np.abs(img_back) # 取绝对值

plt.subplot(221), plt.imshow(img, cmap='gray') #cmap 指定渐变色
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(img_back, cmap='gray')
plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(img_back)
plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
plt.show()

2)opencv中的操作

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('opencv/data/messi5.jpg', 0)
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT) #傅里叶变换(原图,变换模式)结果为双通道,分别存储实数与虚数
dft_shift = np.fft.fftshift(dft)  #将低频转移到图像中间
# cv2.magnitude(x, y) 将sqrt(x ^ 2 + y ^ 2),计算矩阵维度的平方根,即将复数转换为实数
magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))

rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)
#制作四周为0,中间为1的掩模,过滤掉高频成分,相当于模糊边界
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1
fshift = dft_shift * mask  #数组对应位置相乘
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
# cv2.magnitude(x, y) 将sqrt(x ^ 2 + y ^ 2),计算矩阵维度的平方根,即将复数转换为实数
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])

plt.subplot(131), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(img_back, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

2、模板匹配

1)单一匹配

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('opencv/data/messi5.jpg', 0) #0表示读入灰度图
template = cv2.imread('opencv/data/face1.jpg', 0)
w, h = template.shape[::-1] #-1,逆序
#各种比较方式,第三第四的效果不好
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) #eval 语句用来计算存储在字符串中的有效 Python 表达式
    res = cv2.matchTemplate(img2, template, method) #模板匹配(原图,匹配对象,匹配模式)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) #返回矩阵最小值,最大值,最小值索引,最大值索引
    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) #画矩形(背景,左上角,右下角,颜色RGB,线宽)

    plt.subplot(121), plt.imshow(res, cmap='gray') #(原图,渐变色)
    plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(img2, cmap='gray')
    plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
    plt.suptitle('method: ' + meth)
    plt.show()

2)多对象匹配

import cv2
import numpy as np

img_rgb = cv2.imread('../data/mario.png')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('../data/mario_coin.png', 0)
w, h = template.shape[::-1]#-1,逆序索引方式
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)#模板匹配(原图,匹配对象,匹配模式)
loc = np.where(res >=0.85) #返回的是满足条件的元素索引,原数组有多少维,输出的tuple中就包含几个数组
for pt in zip(*loc[::-1]): # *(1,2)转换成二维矩阵,zip将对象中对应的元素打包成一个个元组
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1)#画矩形(背景,左上角,右下角,颜色RGB,线宽)
cv2.imshow("result", img_rgb)
cv2.waitKey(0)

3、霍夫变换-检测简单图形

1)检查直线-cv2.HoughLines

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('opencv/data/sudoku.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#cv2.Canny(原图,下阈值,小于视为非边界,上阈值,超过的视为边界,中间的看是否与边界相连)
edges = cv2.Canny(gray, 10, 50, apertureSize=3) #apertureSize:Sobel算子的大小,可选参数
#cv2.HoughLines(原图,距离精度,角度精度,投票阈值),原图需为二值图,投票阈值可以看作直线的最小长度
lines = cv2.HoughLines(edges, 0.1, np.pi / 180, 200)
for line in lines:  #画直线
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000 * (-b))
    y1 = int(y0 + 1000 * (a))
    x2 = int(x0 - 1000 * (-b))
    y2 = int(y0 - 1000 * (a))
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 1) #画直线(背景,起点,终点,颜色RGB,线宽)
cv2.imshow("houghlines3.jpg", img)
cv2.imshow("edges", edges)
cv2.waitKey(0)

2)检查直线-cv2.HoughLinesP

似乎没有起到效果

import cv2
import numpy as np

img = cv2.imread('../data/sudoku.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#cv2.Canny(原图,下阈值,小于视为非边界,上阈值,超过的视为边界,中间的看是否与边界相连)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
minLineLength = 40 #直线最小长度
maxLineGap = 8  #直线最小距离,范围内的被视为一条直线
#cv2.HoughLinesP(原图,距离精度,角度精度,投票阈值),原图需为二值图,投票阈值可以看作直线的最小长度
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100,maxLineGap,minLineLength)#返回的是直线的端点
print("Len of lines:", len(lines))
for line in lines:
    x1, y1, x2, y2 = line[0]
    cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 1)
cv2.imshow("houghlines3.jpg", img)
cv2.imshow("edges", edges)
cv2.waitKey(0)

3)检测圆环

import cv2
import numpy as np

img = cv2.imread('../data/OpenCV_Logo_with_text.png', 0)
img = cv2.medianBlur(img, 5)#中值滤波(原图,滤波模板尺寸),用于降噪,会损失一些细节
cimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
#HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None)
#HoughCircles(原图,检测模式,累加器比例因子,圆心最小距离,边缘检测阈值,投票阈值,最小圆半径,最大圆半径)
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 0.5, 30, param1=30, param2=35, minRadius=0, maxRadius=0)
circles = np.uint16(np.around(circles)) #取整
print(circles)
for i in circles[0, :]:
    # 画圆,(原图,圆心,半径,线颜色,线粗细)
    cv2.circle(cimg, (i[0], i[1]), i[2], (0, 255, 0), 2)
    cv2.circle(cimg, (i[0], i[1]), 2, (0, 0,255), 3)    #画圆心
cv2.imshow('detected circles', cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

4、图像分割

1)分水岭算法

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('opencv/data/water_coins.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Otsu's thresholding,阈值设为0,cv2.THRESH_OTSU会自动计算一个双峰之间的阈值,返回给retVal参数
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
cv2.imshow('thresh', thresh)
# 开运算:先腐蚀再膨胀就叫做开运算。用来去噪。
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
cv2.imshow('thresh_open', opening)
#膨胀,cv2.dilate(原图,卷积核,迭代次数)
sure_bg = cv2.dilate(opening, kernel, iterations=3)
#距离变换运算(原图,距离类型,卷积核大小),计算非0点到0点的距离
dist_transform = cv2.distanceTransform(opening, 1, 5) #1表示CV_DIST_L2
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)#图像相减
cv2.imshow('unknown', unknown)
#创建标签(原图),返回(连通域的数目,连通域标记)
ret, markers1 = cv2.connectedComponents(sure_fg)
markers = markers1 + 1 #全体加1,为unknown标记腾位置
markers[unknown == 255] = 0
# 实施分水岭算法,边界处标签会改为 -1,(原图,掩模)灰度图可以看成地形图,像素值为高程
markers3 = cv2.watershed(img, markers)
img[markers3 == -1] = [0, 0, 255]
cv2.imshow('watershed', img)
cv2.waitKey(0)

2)GrabCut算法:是一种概率统计的聚类算法

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('../data/messi5.jpg')

mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1, 65), np.float64) #算法内部数组
fgdModel = np.zeros((1, 65), np.float64) #算法内部数组
rect = (50, 50, 450, 290) #包含前景的矩形,格式为 (x,y,w,h)
# cv2.grabCut:函数的返回值是更新的 mask, bgdModel, fgdModel
# iterCount迭代次数
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount=5, mode=cv2.GC_INIT_WITH_RECT)
#修改掩模图像,所有的0像素和2像素都被归为0(例如背景),所有的 1 像素和 3 像素都被归为 1(前景)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img = img * mask2[:, :, np.newaxis] #np.newaxis插入新维度,对应点相乘,广播机制
# 修正
newmask = cv2.imread('../data/messi5_new.jpg',0)
mask[newmask == 0] = 0  #添加背景辅助线
mask[newmask == 255] = 1  #添加前景辅助线
mask, bgdModel, fgdModel = cv2.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_MASK)
mask = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img_1 = img * mask[:, :, np.newaxis]
cv2.imshow('img_1',np.hstack([img,img_1]))
cv2.waitKey(0)

5、特征检测

1)Harris角点检测,R=\lambda _{1}\lambda _{2}-k(\lambda _{1}+\lambda _{2})^{2},分别检测上下移动偏差

import cv2
import numpy as np

img = cv2.imread('../data/chessboard.png')
# img = cv2.imread('../data/timg.jpg')
img = cv2.resize(img, (640, 480))  #修改图片大小
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #转换灰度图
gray = np.float32(gray)
# 寻找角点:输入图像必需是 float32 最后一个参数在 0.04 到 0.05 之间
dst = cv2.cornerHarris(gray,5, 5, 0.04) #(原图,窗口大小,卷积核大小,自由参数)
dst = cv2.dilate(dst, None) #膨胀
img[dst > 0.1 * dst.max()] = [0, 0, 255] #在原图中标记角点

#亚像素级精度
dst = np.uint8(dst)
ret, dst = cv2.threshold(dst, 0.1 * dst.max(), 255, 0) #二值化
#进行连通域提取,返回值(连通域数目,连通域标记图,连通域统计信息列表,连通域中心点)
ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)#原图,8位单通道
#停止优化的标准:(位置变化最小,最大迭代次数)
criteria = (cv2.TERM_CRITERIA_MAX_ITER+cv2.TERM_CRITERIA_EPS, 10, 0.01)
#cv2.cornerSubPix(原图,角点,窗口大小,核大小(-1,-1)表示忽略,停止优化标准)
corners = cv2.cornerSubPix(gray, np.float32(centroids), (5, 5), (-1, -1), criteria) #返回角点
res = np.hstack((centroids, corners))  #水平方向平铺
res = np.int0(res) #numpy.int0 就是numpy.int64
img[res[:, 1], res[:, 0]] = [0, 0, 255]
img[res[:, 3], res[:, 2]] = [0, 255, 0]
print(res)
cv2.imshow('dst', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

2)Shi-Tomasi角点检测,R=min[\lambda _{1},\lambda _{2}]

import numpy as np
import cv2
from matplotlib import pyplot as plt

filename = '../data/blox.jpg'
img = cv2.imread(filename)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#计算角点(原图,最大角点数,角点质量下限,最小角点距离)
corners = cv2.goodFeaturesToTrack(gray, maxCorners=25, qualityLevel=0.01, minDistance=10)
corners = np.int0(corners)  #转换为整数类型
print(corners)
for i in corners:
    x, y = i.ravel()
    cv2.circle(img, (x, y), 3, (0,255,0), -1)

plt.imshow(img), plt.show()

3)FAST角点检测

import cv2

img = cv2.imread('../data/blox.jpg', 0)
fast = cv2.FastFeatureDetector_create() #创建检测器对象
kp = fast.detect(img, None) #进行角点检测
img2 = cv2.drawKeypoints(img, kp, None, color=(255, 0, 0)) #画关键点
# 输出默认参数
print("Threshold: ", fast.getThreshold())  #返回阈值
print("nonmaxSuppression: ", fast.getNonmaxSuppression())  #是否使用非极大值抑制
print("neighborhood: ", fast.getType())
print("Total Keypoints with nonmaxSuppression: ", len(kp))  #关键点个数
cv2.imshow('img2',img2)
fast.setNonmaxSuppression(0)  #关闭非极大值抑制
kp = fast.detect(img, None)
print("Total Keypoints without nonmaxSuppression: ", len(kp))
img3 = cv2.drawKeypoints(img, kp, None, color=(255, 0, 0))
cv2.imshow('img3',img3)
cv2.waitKey(0)

4)ORB角点检测,快速低消耗的算法

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('../data/blox.jpg', 0)
# 创建检测器对象
orb = cv2.ORB_create()
# 检测角点
kp = orb.detect(img, None)
# 统计描述信息
kp, des = orb.compute(img, kp)
# 画角点
img2 = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0), flags=0)
plt.imshow(img2), plt.show()

6、特征匹配

1)cv2.BFMatcher:蛮力匹配

import cv2
import matplotlib.pyplot as plt

img1 = cv2.imread('../data/box.png', 0)  # queryImage
img2 = cv2.imread('../data/box_in_scene.png', 0)  # trainImage
# 创建检测器对象
orb = cv2.ORB_create()
# 检测角点,描述特征
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# 创建特征匹配器对象
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# 进行特征匹配
matches = bf.match(des1, des2)
# 对匹配结果排序
matches = sorted(matches, key=lambda x: x.distance)
# 画前10个匹配出的特征
# img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], flags=2)  # 前10个匹配
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None,flags=2)  # 前10个匹配
plt.imshow(img3), plt.show()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值