1.问题背景:

给一张图片和模板图片(如下图),需要用传统机器视觉的方法来提取他们不一样的特征(也就是划痕部分),并把划痕转为二值化


1.1 才开始使用基于灰度的方法:

因为划痕和旁边背景颜色比较接近,绘制出的灰度直方图变化不大,调了很久阈值也不能分出划痕部分,效果如下:


1.2 后来直接使用图像相减,RGB和Gray分别图像相减结果得到如下:


解决方案:

应该是没有配准而相减有边框的,最终决定配准后,图像相减
查阅资料文献后,大致思路如下:
1. RGB—> 灰度图
2. 去噪滤波,图像增强等一系列预处理操作
3. 提特征点(ORB)并进行图像配准
4. 配准后进行二值化
5. 图像相减操作(ImageChops.difference)

1. RGB-----> Gray

#  1. 转为灰度图
target = cv2.imread("2368_data.png")
gray_target=cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
template = cv2.imread("2368_model.png")
gray_template=cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)

2. 去噪滤波 预处理操作

# 去噪滤波 预处理
target_gauss = cv2.GaussianBlur(gray_target,(3, 3),1,1)
template_gauss = cv2.GaussianBlur(gray_template,(3, 3),1,1)# plt转为cv
target_gauss =Image.fromarray(target_gauss) # np array
template_gauss =Image.fromarray(template_gauss) # np array# 亮度增强
bright=  0.9
bright_target=ImageEnhance.Brightness(target_gauss).enhance(bright)
bright_template=ImageEnhance.Brightness(template_gauss).enhance(bright)#色度增强
color = 1.2
colored_target = ImageEnhance.Color(bright_target).enhance(color)
colored_template = ImageEnhance.Color(bright_template).enhance(color)# 对比度增强
contrast =1.1
contrasted_target = ImageEnhance.Contrast(colored_target).enhance(contrast)
contrasted_template = ImageEnhance.Contrast(colored_template).enhance(contrast)# 锐度增强
sharpness = 18.0
shaped_target= ImageEnhance.Sharpness(contrasted_target).enhance(sharpness)
shaped_template= ImageEnhance.Sharpness(contrasted_template).enhance(sharpness)plt.subplot(121), plt.imshow(shaped_target, cmap='gray')
plt.title('shaped_target'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(shaped_template, cmap='gray')
plt.title('shaped_template'), plt.xticks([]), plt.yticks([])
plt.show()

1.只做高斯去噪,不做亮度,锐化等预处理后的图片:

2.不进行高斯去噪,只进行预处理的图:
灰度后的图片会产生很多噪点,因此进行去噪滤波还是有一定效果的。
去噪

3.做完高斯去噪以及一系列亮度,锐化预处理后的图片:
(具体参数还没有详细调,只是先按这个值先设置)

3. 提特征点(ORB或SURF)并进行图像配准

3.1 理论部分

参考资料《mage Alignment (Feature Based) using OpenCV (C++/Python)》

核心思想:
在一个图像中检测到一组特征点,并与另一张图像中的特征点相匹配。然后根据这些匹配的特征点计算出一个转换规则,从而将一个图像映射到另一个图像上。
主要应用就是扫描软件,合成全景图片等。

图像对齐技术的核心是一种维数3X3的单应性矩阵(Homography )

图像配准步骤:

  1. 读取图片
  2. 检测特征点:为两张图检测ORB特征点。为了计算单应性矩阵4个就够了,但是一般会检测到成百上千的特征点。可以使用参数MAX_FEATURES来控制检测的特征点的数量。检测特征点并计算描述子的函数是detectAndCompute。
  3. 特征匹配:找到两图中匹配的特征点,并按照匹配度排列,保留最匹配的一小部分。然后把匹配的特征点画出来并保存图片到磁盘。我们使用Hamming来度量两个特征点描述子的相似度。下图中把匹配的特征点用线连起来了。注意,有很多错误匹配的特征点,所以下一步要用一个健壮的算法来计算单应性矩阵。
  4. 计算单应性矩阵:上一步产生的匹配的特征点不是100%正确的,就算只有20~30%的匹配是正确的也不罕见。findHomography函数使用一种被称为随机抽样一致算法(Random Sample Consensus )的技术在大量匹配错误的情况下计算单应性矩阵。
  5. 扭转图片(Warping image):有了精确的单应性矩阵,就可以把一张图片的所有像素映射到另一个图片。warpPerspective函数用来完成这个功能。

如何把两张图像中的特征点匹配起来呢?
SIFT一般的可以使用K近邻(KNN)算法。K近邻算法求取在空间中距离最近的K个数据点,并将这些数据点归为一类。在进行特征点匹配时,一般使用KNN算法找到最近邻的两个数据点,如果最接近和次接近的比值大于一个既定的值,那么我们保留这个最接近的值,认为它和其匹配的点为good match(有Lowe在SIFT论文中提出)


单应性矩阵Homography Matrix

找到特征点并匹配起来后,如何让两张图片对齐呢?
这就用到了单应性矩阵了。Homography这个词由Homo和graphy,Homo意为同一,graphy意为图像,也就是同一个东西产生的图像。不同视角的图像上的点具有如下关系:

其中[x1 y1 1]和[x2 y2 1]分别表示对应像素的齐次坐标。单应性矩阵就是下面这个矩阵:

可以看到,单应性矩阵有八个参数,如果要解这八个参数的话,需要八个方程,由于每一个对应的像素点可以产生2个方程(x一个,y一个),那么总共只需要四个像素点就能解出这个单应性矩阵。

那么应该选择哪四个点来计算Homography matrix呢?
RANSAC算法巧妙的解决了这一问题。

随机抽样一致算法(Random sample consensus:RANSAC)

说道估算模型的算法,很容易想到最小二乘法。最小二乘法在数据误差比较小的情况下是可以的,但是针对噪声很大的数据集的时候,容易出问题,我们可以通过下面的例子来说明

很明显,我们的数据应该是一条由左下到右上的一条线,但是由于离群数据太多(左上和右下区域),如果用最小二乘法的话,就无法准确的找到我们期望的模型(因为最小二乘法无法剔除误差很大的点,一视同仁的将所有的点都用于模型的计算)。RANSAC(Random Sample Consensus)算法的不同之处就在于,它能够有效的去除误差很大的点,并且这些点不计入模型的计算之中。

所以,在得到了众多的匹配点以后,使用RANSAC算法,每次从中筛选四个随机的点,然后求得H矩阵,不断的迭代,直到求得最优的H矩阵为止。所以在前面使用cv2.findHomography方法时,参数cv2.RANSAC表明使用RANSAC算法来筛选关键点

3.2 代码部分

  1. 读取图片并创建ORB
import cv2 as cv
image1 = cv.imread('1.png')
image2 = cv.imread('2.png')
# 初始化ORB
orb = cv.ORB_create()
  1. 寻找关键点和描述子
 # 寻找关键点kp1 = orb.detect(img1)kp2 = orb.detect(img2)# 计算描述符
kp1,des1=orb.detectAndCompute(img1,None)  # 计算哪张图片的用哪张图片的关键点。
kp2,des2=orb.detectAndCompute(img2,None) 

找到了关键点可以画出关键点看一看:

# 画出关键点
outimg1 = cv.drawKeypoints(img1, keypoints=kp1, outImage=None)
outimg2 = cv.drawKeypoints(img2, keypoints=kp2, outImage=None)# 这里是把两张图片在同一个窗口中显示。
import numpy as np
outimg3 = np.hstack([outimg1, outimg2])
cv.imshow("Key Points", outimg3)
cv.waitKey(0)

  1. 关键点匹配
    有了关键点和描述子,我们就要对这些点进行匹配。这里我们用的是Brute-Force匹配器,它获取第一组中一个特征的描述符,并通过一些距离计算与第二组中的所有其他特征匹配,最接近的一个被返回。
 # 初始化 BFMatcherbf = cv.BFMatcher(cv.NORM_HAMMING)# 对描述子进行匹配matches = bf.match(des1, des2)
  1. 对匹配点进行筛选并画出匹配图
good_match=sorted(mathces,key=lambda x:x.distance) #据距离来排序
result= cv2.drawMatches(gray_target,kp1, gray_template,kp2,good_match,outImg=None) #画出匹配关系
cv2.namedWindow('Match Result',cv2.WINDOW_NORMAL)
cv2.imshow("Match Result", result)
cv2.waitKey(0)

  1. 计算单应性矩阵 (findHomography函数)

首先找出target和template中的特征点,然后找到较好的匹配点对good_match(判断good_match是否大于4,至少4个匹配点才能构建矩阵),最后通过warpPerspective方法对图像target进行投影映射。

 if len(goodMatch) > 4:ptsA= np.float32([kp1[m.queryIdx].pt for m in goodMatch]).reshape(-1, 1, 2)ptsB = np.float32([kp2[m.trainIdx].pt for m in goodMatch]).reshape(-1, 1, 2)ransacReprojThreshold = 4H, status =cv2.findHomography(ptsA,ptsB,cv2.RANSAC,ransacReprojThreshold);imgOut = cv2.warpPerspective(img2, H, (img1.shape[1],img1.shape[0]),flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)

cv2.warpPerspective(img,H,(img1.shape[1],img1.shape[0]),cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)

第一个参数为需要投影的图像(img2)
第二个参数为单应性矩阵(H)
第三个参数为所得图像的矩阵大小((img1.shape[1],img1.shape[0]) )
最后的参数cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP,为插值时使用的插值方法INTER_LINEAR,cv2.WARP_INVERSE_MAP则将M设置为dst—>src的方向变换。


遇到的问题:
kp1求出来的特征点只有两个,构建单应性矩阵最少需要4个,故一直报错

后来查询到ORB产生的特征点在点特征提取算法中最少(详细特征提取算法比对参考Related-8),因此换成了KAZE检测器,产生的特征点很明显增多,匹配显示结果如下:

最终的透视变换结果如下:

emmmm…后来发现自己可能不需要透视变换,只需要简单的平移对齐就好,于是改成仿射变换的矩阵


Tips

1. plt 与opencv相互转换

plt转为opencv

from PIL import Image
import numpy as np
import cv2
img=Image.open(path)
#PIL转ndarray
img=np.array(img)
img=img[:,:,(2,1,0))]
#show
cv2.imshow('img',img)
cv2.waitKey(0)
#write
cv2.imwrite(path,img)

opencv 转为 plt

img=Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)))
#img=Image.fromarray(img)
plt.imshow(img)
#show
plt.show()
#save、dpi为分辨率
plt.savefig(path,dpi=100)

2.仿射变换和透视变换

简单写一下:
仿射变换:线性变换+平移,二维图像---->二维图像

透射变换:线性变换+平移,二维图像---->投影到三维平面----->转为二维坐标,因此它是空间上的调整,比如图片弯曲

区别是:仿射变换是(2x3)的变换矩阵,透射变换是(3x3)的变换矩阵

Related

1.Image Alignment (ECC) in OpenCV ( C++ / Python )
2.OpenCV快速入门——图像预处理(必看)
3.opencv+python实现图像匹配----模板匹配、特征点匹配
4.Nice!!!Python进行SIFT图像对准
5.图像对齐(图像配准)方法记录
6.OpenCV-Python Feature2D 特征点检测(含SIFT/SURF/ORB/KAZE/FAST/BRISK/AKAZE)
7.OpenCV-Python ORB特征匹配(实践篇)
8.报错等问题:
第6章 特征检测、匹配与搜索 个人笔记
9.基于机器视觉的PCB缺陷检测与分类识别
10.OPENCV特征点提取算法对比

opencv图像对齐与图像相减python相关推荐

  1. 图像对齐(图像配准)方法记录

    图像对齐方法 1.基于ORB特征的方法 1.检测两张图的ORB特征点 2.特征匹配 3.计算单应性矩阵 4.扭转图片 图示 具体的代码实现可以参考这篇文章:https://blog.csdn.net/ ...

  2. opencv2_蓝屏抠图(图像相减并去噪)

    问题描述: Ø 蓝屏抠图 建立一个纯色背景(如蓝色或绿色),先拍摄一幅空背景图像,再在背景前拍摄一幅自己的图像,尝试将两幅图像的对应像素相减并去噪,实现人像的抠图处理. C++代码: #include ...

  3. Opencv中的图像相加,相减,相除,相乘(python实现)

    文章目录 1.相加 2.减法 3.乘法 4.除法 1.相加 代码实战 import os import cv2 import numpy as np#读取图片和缩放图片 lenna=cv2.imrea ...

  4. Python与机器视觉(x)图像差分-图像相减

    本系列博客主要分享Python在机器视觉/计算机视觉下的编程应用 cv2包是著名的视觉库OpenCV的Python实现 在求峰值信噪比PSNR时,我们需要求取目标图像和实际图像之间的误差. err = ...

  5. MATLAB——基于图像相减的纸牌识别系统

    MATLAB------基于图像相减的纸牌识别系统 一.设计要求 二.编程思路 1.获取模板(含代码) 2.输入图像测试(含代码) 三.测试结果 四.性能分析 五.另外一道编程题(没错,就是手写数字识 ...

  6. python计算机视觉-- 基于OpenCV的图像分割和图像融合系统

    目录 前言 一.需求分析 二.概要设计 2.1 基本原理 2.2 界面设计 三.详细设计 3.1 系统流程图 3.2 数据集 3.3 代码实现 3.3.1 利用deeplabV3模型分割 3.3.2  ...

  7. 使用Python,OpenCV进行去水印,图像修复

    图像修复是图像保存和图像恢复的一种形式,其历史可以追溯到1700年代,当时意大利威尼斯的公共图片修复总监彼得·爱德华兹(Pietro Edwards)应用这种科学方法来修复和保存著名作品(资料来源). ...

  8. 使用Python,OpenCV+OCR检测护照图像中的机器可读区域(MRZ Machine-Readable Zones)

    使用Python,OpenCV+OCR检测护照图像中的机器可读区域(MRZ Machine-Readable Zones) 1. 效果图 2. 原理 3. 源码 参考 这篇博客将介绍如何只使用基本的图 ...

  9. python opencv二值化图像_python opencv,读取彩色图像,提取三通道,图像二值化,提取图像的边缘...

    python opencv,读取彩色图像,提取三通道,图像二值化,提取图像的边缘 python opencv 1,读取图像 2,图像变矩阵 3,图像转灰度图像 4,彩色图像是3D数组 5,灰度图像是2 ...

最新文章

  1. NanoPi NEO Air使用十六:使用python做开发
  2. LeetCode --- Validate Binary Search Tree
  3. linux系统下网络连接不上的问题
  4. 快手副总裁林粼:快手将从事5G相关业务线研究布局
  5. 《推荐系统笔记(四)》svd的python计算实例
  6. centos操作系统版本获取
  7. mybatis-plus超详细讲解
  8. Ubuntu Linux 环境变量PATH设置
  9. Tomcat:开启Tomcat服务CMD窗口乱码
  10. JasperReports学习(1)
  11. 网站被黑检测-网页挂马及暗链检测
  12. MongoDB (芒果)安装说明创建与插入数据
  13. Moore-Penrose伪逆(Moore-Penrose广义逆)
  14. 计算机网络八大性能指标
  15. 笔记本电脑亮度调节键失灵了,该怎么解决?
  16. 综合日语第一册第八课
  17. ECCVW 2022 | 第二届城市规模点云语义理解挑战赛
  18. 如何理解电商的B2B模式与B2C模式
  19. 计算机管理恢复分区,windows10系统隐藏恢复分区Recovery Image的方法
  20. 网络交互实验实验总结

热门文章

  1. Bugzilla使用手册
  2. 网站只有首页能打开,其他页面404
  3. 网络互联技术(1)——前篇—【转载】计算机发展史
  4. Win10+Python3+OpenCV+CUDA——在win中配置OpenCV4.5并与Python环境绑定
  5. kendoUI系列教程之DropDownList下拉菜单
  6. 随机数产生器(random number generator)
  7. fedora26下解决wps字体缺失(添加windows字体)
  8. package.json 详解
  9. C++的explicit是什么?
  10. 医药公司协同电子商务系统