使用OPENCV3图像对齐

图1. 左:一幅来自- 的图片(未对齐);右:对齐后图像
1. 左边的图像是一个具有历史意义的照片的集合称为-集 。图像是由使用一个早期的彩色摄像机拍摄 。因为相机的机械性质,图像的颜色通道未对齐 。右边的图像通过进行对齐后的图像 。
可以从这里的下载部分中的所有示例中的所有示例代码 。
在这篇文章中,我们将开始一个有趣的彩色摄影的历史 。这篇文章是致力于彩色摄影的早期先驱,使我们能够捕捉和存储我们的记忆中的颜色 。
2. 一个简短的彩色照片发展过程
由 和拍摄的首张3灰度图像
由James Clerk 在1855年提出,我们可以用滤光片(红,绿 , 蓝)进行滤光后拍摄,然后再将这三个图片结合起来 。在1861年,英国摄影师利用这个方法拍摄了第一张彩色图像 。他获取了图片的三个灰度图,然后进行了叠加 。但是,这个方法存在一个问题,因为当时可用的感光材料对蓝光敏感 , 但对绿光不敏感,对红光几乎不敏感 。虽然它的实践是革命性的,但这种方法是不实际的 。
到了20世纪初,感光材料的敏感度已经大大提高,并在前十年有几种相机已经可用于彩色摄影 。在这些相机 , 最流行的彩色相机,由Lumière兄弟发明 。
最具有竞争性的相机系统是由Adolf 设计,并由 制造,被称之为 Dr. ’s - 。其中意为三色 。同时这个相机有一个长的玻璃板,可以同时放下三色滤光片 。
利用这个相机,-在长达十年的时间里拍摄了俄罗斯近10000张图片,幸运的,这些图片保留了下来 。从这些黑白图像生成一个彩色图像是不平凡的(如图3所示) 。相机是一个机械装置,这三个图片的跨度超过2-6秒 。因此,三频道经常失准,简单地堆积起来导致了一个很不理想,结果如图1所示 。
运动模块
在一个典型的图像对齐问题,一个场景我们有两个图像,他们运动模型都是相关的 。不同的图像对准算法的目的是估计这些运动模型的参数,使用不同的参数和假设 。一旦这些参数是已知的,就可以直接从一幅图像变换到另一个
让我们快速看看这些运动模型看起来像什么 。
():第一图像可以平移(x,y)所获得的第二图像 。只有两个参数X和Y,我们需要估计 。
():第一幅图像旋转和移动版本 。所以有三个参数X,Y和角度 。你会注意到在图4中,当一个正方形进行欧氏变换,大小不改变 , 平行线保持平行,并且在变换后的直角保持不变 。
():仿射变换是一个组合的旋转,平移(移位),规模,和剪切 。这个变换有六个参数 。当一个正方形进行仿射变换时,平行线保持平行 , 但在直角相交的线不再保持正交 。
单应性():所有上述二维变换变换 。他们没有考虑到3D效果 。单应变换另一方面可以考虑一些3D效果(但不是全部) 。这个变换有8个参数 。当一方转化使用单应能改变任何四边形 。
在的仿射变换,储存在一个2 x 3大小的矩阵 。平移和欧氏变换是仿射变换的特殊情况 。在平移过程中 , 旋转、尺度和剪切参数为零 , 而在欧氏变换中的尺度和剪切参数都为零 。因此,移动和欧氏变换也存储在一个2×3矩阵 。一旦这个矩阵估计(我们将在下一节中看到),可以对图像进行功能 。
单应性,存储在一个3×3矩阵 。一旦单应估计,图像可以被纳入对齐使用 。
【使用OPENCV3图像对齐】使用增强的相关系数图像配准(ECC)最大化
ECC的图像对准算法中引入了 3是基于2008篇题为参量图像对齐使用增强的相关系数最大化的 D. 和 Z.。他们建议使用一种新的相似性度量称为增强型相关系数(ECC)的运动模型的参数估计 。使用他们的方法有两个优点 。
不同于像素强度差异的传统的相似性度量 , ECC是光度失真的对比度和亮度不变 。
虽然目标函数是参数的非线性函数,但他们发展的迭代格式来求解优化问题是线性的 。换言之,他们采取了一个问题,看起来在计算复杂的表面上 , 并找到一个简单的方法来解决它迭代 。
在中使用
在中我们使用有以下步骤:
读取图像 。

使用OPENCV3图像对齐

文章插图
将它们转换为灰度图 。
选择一个你想估计的模型 。
分配空间()存储运动模型 。
定义一个终止准则,告诉该算法什么时候停止 。
估计使用运动矩阵 。
将经矩阵应用到图像中的一个与其他图像对齐 。
// Read the images to be alignedMat im1 = imread("images/image1.jpg");Mat im2 = imread("images/image2.jpg");// Convert images to gray scale;Mat im1_gray, im2_gray;cvtColor(im1, im1_gray, CV_BGR2GRAY);cvtColor(im2, im2_gray, CV_BGR2GRAY);// Define the motion modelconst int warp_mode = MOTION_EUCLIDEAN;// Set a 2x3 or 3x3 warp matrix depending on the motion model.Mat warp_matrix;// Initialize the matrix to identityif ( warp_mode == MOTION_HOMOGRAPHY )warp_matrix = Mat::eye(3, 3, CV_32F);elsewarp_matrix = Mat::eye(2, 3, CV_32F);// Specify the number of iterations.int number_of_iterations = 5000;// Specify the threshold of the increment// in the correlation coefficient between two iterationsdouble termination_eps = 1e-10;// Define termination criteriaTermCriteria criteria (TermCriteria::COUNT+TermCriteria::EPS, number_of_iterations, termination_eps);// Run the ECC algorithm. The results are stored in warp_matrix.findTransformECC(im1_gray,im2_gray,warp_matrix,warp_mode,criteria);// Storage for warped image.Mat im2_aligned;if (warp_mode != MOTION_HOMOGRAPHY)// Use warpAffine for Translation, Euclidean and AffinewarpAffine(im2, im2_aligned, warp_matrix, im1.size(), INTER_LINEAR + WARP_INVERSE_MAP);else// Use warpPerspective for HomographywarpPerspective (im2, im2_aligned, warp_matrix, im1.size(),INTER_LINEAR + WARP_INVERSE_MAP);// Show final resultimshow("Image 1", im1);imshow("Image 2", im2);imshow("Image 2 Aligned", im2_aligned);waitKey(0);
彩色图的重建
上面的影像也在-采集部分 。左边是未对齐的RGB通道的图像,右边是调整后的图像 。这张照片还显示 , 在第二十世纪初的照片板是敏感的,捕捉到的颜色光谱很广 。鲜艳的红色,蓝色和绿色 。
在前面的章节中的代码可以用来解决一个图像配准问题 。然而 , 如果你用它来重建上述形象,你会感到非常失望 。在现实世界中的计算机视觉是艰难的 。
问题是,如果在一个图像中的红色,绿色和蓝色通道是不强烈相关 。例如,检查出蓝色礼服的埃米尔图3穿 。在三个渠道看起来有很大的不同 。然而,即使强度是不同的,在三个通道中的东西是相似的 , 因为一个人的眼睛可以很容易地告诉它,它是相同的场景 。
事实证明,在梯度域的图像的三个通道的更强烈的相关性 。这并不奇怪 , 因为即使在三个通道中的强度可能是不同的,由对象和颜色边界所产生的边缘地图是一致的 。
using namespace cv;using namespace std;Mat GetGradient(Mat src_gray){Mat grad_x, grad_y;Mat abs_grad_x, abs_grad_y;int scale = 1;int delta = 0;int ddepth = CV_32FC1; ;// Calculate the x and y gradients using Sobel operatorSobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );convertScaleAbs( grad_x, abs_grad_x );Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );convertScaleAbs( grad_y, abs_grad_y );// Combine the two gradientsMat grad;addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );return grad;
using namespace cv;using namespace std;// Read 8-bit color image.// This is an image in which the three channels are// concatenated vertically.Mat im =imread("images/emir.jpg", IMREAD_GRAYSCALE);// Find the width and height of the color imageSize sz = im.size();int height = sz.height / 3;int width = sz.width; // Extract the three channels from the gray scale imagevectorchannels;channels.push_back(im( Rect(0, 0,width, height)));channels.push_back(im( Rect(0, height,width, height)));channels.push_back(im( Rect(0, 2*height,width, height))); // Merge the three channels into one color imageMat im_color;merge(channels,im_color);// Set space for aligned image.vector aligned_channels;aligned_channels.push_back(Mat(height, width, CV_8UC1));aligned_channels.push_back(Mat(height, width, CV_8UC1));// The blue and green channels will be aligned to the red channel.// So copy the red channelaligned_channels.push_back(channels[2].clone());// Define motion modelconst int warp_mode = MOTION_AFFINE;// Set space for warp matrix.Mat warp_matrix;// Set the warp matrix to identity.if ( warp_mode == MOTION_HOMOGRAPHY )warp_matrix = Mat::eye(3, 3, CV_32F);elsewarp_matrix = Mat::eye(2, 3, CV_32F);// Set the stopping criteria for the algorithm.int number_of_iterations = 5000;double termination_eps = 1e-10;TermCriteria criteria(TermCriteria::COUNT+TermCriteria::EPS,number_of_iterations, termination_eps);// Warp the blue and green channels to the red channelfor ( int i = 0; i < 2; i++){double cc = findTransformECC (GetGradient(channels[2]),GetGradient(channels[i]),warp_matrix,warp_mode,criteria);if (warp_mode == MOTION_HOMOGRAPHY)// Use Perspective warp when the transformation is a HomographywarpPerspective (channels[i], aligned_channels[i], warp_matrix, aligned_channels[0].size(), INTER_LINEAR + WARP_INVERSE_MAP);else// Use Affine warp when the transformation is not a HomographywarpAffine(channels[i], aligned_channels[i], warp_matrix, aligned_channels[0].size(), INTER_LINEAR + WARP_INVERSE_MAP);} // Merge the three channelsMat im_aligned;merge(aligned_channels, im_aligned);// Show final outputimshow("Color Image", im_color);imshow("Aligned Image", im_aligned);waitKey(0);