一、题目
Sergei Mikhailovich Prokudin-Gorskii (1863 - 1944)是一位超越其所在时代的人,早在1907年,他就坚信彩色摄影将成为未来的发展趋势。在当时,由于沙皇的特别许可,他可以周游辽阔的沙俄帝国并拍摄他所看到的事物,包括列夫·托尔斯泰唯一的彩色肖像。他用简单原始的彩色摄影法拍下了很多东西:人、建筑、风景、铁路、桥梁……!其所采用的彩色摄影法很简单:分别用红、绿、蓝滤光片把每个场景的三次曝光记录到一个玻璃底板上,并设想通过特殊的投影装置将三种颜色的底片叠加显示,从而让观众能够通过彩色照片了解这个幅员辽阔的国家。可惜,他的计划从未实现:他在1918年的十月革命后离开了俄罗斯,再也没有回来。幸运的是,他所拍摄的沙俄帝国最后几年的RGB玻璃板底片保存了下来,并于1948年被美国国会图书馆(LoC)买下。LoC最近将底片数字化,并可以通过网络供公众下载。
本次实验的目的是利用图像处理技术,基于数字化存储的玻璃底板图像自动生成尽量非虚化的彩色图像。为完成本次实验,你需要从原始图像文件中分割提取三个彩色通道图像,将它们对齐并彼此叠加在一起,最终形成一张RGB彩色图像。美国国会图书馆在其网站上详细说明了他们对这批照片进行复原并创建彩色图像的过程,大家可以参考 http://www.loc.gov/exhibits/empire/making.html
即将如下图片转化为彩色图
二、解决方案
2.1 方案一
(1)为处理方便及节省磁盘空间,将所有tif图片转化为jpg格式,并压缩到394x1024像素。
def covert_zip():
img_fold_A = 'E:/QQ/test1/before'
img_list1 = os.listdir(img_fold_A)
num_imgs1 = len(img_list1)
for i in range(num_imgs1):
save_fold_A = 'E:/QQ/test1/after'
name_A = img_list1[i]
path_A = os.path.join(img_fold_A,
name_A)
im_A = cv2.imread(path_A, 1)
if('.tif' in name_A):
file_name_temp = name_A[:-4]
file_name =
os.path.join(save_fold_A , file_name_temp+'.jpg')
cv2.imwrite(file_name, im_A)
image = cv2.imread(file_name)
res = cv2.resize(image, (394,1024),
interpolation=cv2.INTER_AREA)
cv2.imwrite(file_name,res)
else:
file_name_temp = name_A[:-4]
file_name = os.path.join(save_fold_A ,
file_name_temp+'.jpg')
cv2.imwrite(file_name, im_A)
(2)从处理好的文件夹中依次读入图片,先将图片裁剪成三等份,即B、G、R。然后依次对图片进行对齐处理和合并,最终得到RGB三通道彩图。
首先寻找特征点:检测图像中的ORB特征。虽然我们只需要4个特征来计算单应性,但通常在两个图像中检测到数百个特征。使用Python代码中的参数MAX_FEATURES来控制功能的数量。
特征点匹配:我们在两个图像中找到匹配的特征,按匹配的评分对它们进行排序,并保留一小部分原始匹配。我们使用汉明距离(hamming distance)作为两个特征描述符之间相似性的度量。当然其中有许多不正确的匹配。
**计算Homography:**当我们在两个图像中有4个或更多对应点时,可以计算单应性。自动功能匹配并不总能产生100%准确的匹配。20-30%的匹配不正确并不罕见。幸运的是,findHomography方法利用称为随机抽样一致性算法(RANSAC)的强大估计技术,即使在存在大量不良匹配的情况下也能产生正确的结果。
图像映射:一旦计算出准确的单应性,我可以应用于一个图像中的所有像素,以将其映射到另一个图像。这是使用OpenCV中的warpPerspective函数完成的。
具体代码如下:
def alignImages(im1,im2):
# Convert images to grayscale
#im1Gray = cv2.cvtColor(im1,
cv2.COLOR_BGR2GRAY)
#im2Gray = cv2.cvtColor(im2,
cv2.COLOR_BGR2GRAY)
# Detect ORB features and compute
descriptors.
orb = cv2.ORB_create(MAX_FEATURES)
keypoints1, descriptors1 =
orb.detectAndCompute(im1, None)
keypoints2, descriptors2 =
orb.detectAndCompute(im2, None)
#print(descriptors1.shape)
#print(descriptors2.shape)
# Match features.
matcher =
cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
matches = matcher.match(descriptors1,
descriptors2, None)
# Sort matches by score
matches.sort(key=lambda x: x.distance,
reverse=False)
# Remove not so good matches
numGoodMatches = int(len(matches) *
GOOD_MATCH_PERCENT)
matches = matches[:numGoodMatches]
# Draw top matches
imMatches = cv2.drawMatches(im1, keypoints1,
im2, keypoints2, matches, None)
# Extract location of good matches
points1 = np.zeros((len(matches), 2),
dtype=np.float32)
points2 = np.zeros((len(matches), 2),
dtype=np.float32)
for i, match in enumerate(matches):
points1[i, :] = keypoints1[match.queryIdx].pt
points2[i, :] =
keypoints2[match.trainIdx].pt
# Find homography
h, mask = cv2.findHomography(points1,
points2, cv2.RANSAC)
# Use homography
height, width = im2.shape
im1Reg = cv2.warpPerspective(im1, h, (width,
height))
return im1Reg
3)对合成后图像进行边缘检测,然后裁剪去除周围白色、黑色或其他异常颜色的边框。
获取图片,转换灰度
img_gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
提取图像的梯度:以sobel算子计算x,y防线上的梯度,之后在x方向上减去y方向上的梯度,通过这个减法,留下具有高水平梯度和低垂直梯度的图像区域。
gradX = cv2.Sobel(img_gray,
ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(img_gray,
ddepth=cv2.CV_32F, dx=0, dy=1, ksize=-1)
img_gradient = cv2.subtract(gradX, gradY)
img_gradient =
cv2.convertScaleAbs(img_gradient)
去除噪声:使用低通滤波器平滑图像,有助于平滑图像中的高频噪声,其目标是为了降低图像的变化率,然后对模糊图像二值化,以便于找到图像轮廓。
blurred = cv2.blur(img_gradient, (9, 9))(_,thresh) = cv2.threshold(blurred, 90, 255, cv2.THRESH_BINARY)
图像形态学:选取RECT核,采用closed操作,得到整个轮廓
细节刻画:和原图对比有细节丢失,会干扰后面的轮廓检测,因此需要扩充,分别执行4次形态学腐蚀和膨胀。
找出轮廓:采用cv2.findContours()函数,第一个参数是要检索的图片,必须是二值图(即黑白并非灰图),第二个参数是轮廓类型,采用cv2.RETR_EXTERNAL即只检测外轮廓,第三个参数是处理近似方法,采用
画出轮廓:采用drawContours()函数画出轮廓来,box里面保存的是轮廓四个顶点的坐标。
裁剪:找出四个顶点的x,y坐标最大最小值,然后根据本次实验具体图片调整,得到新图像的高和宽。
2.2方案二
由于方案一中将所有的tif都转换成了jpg格式,并做了压缩处理,导致原tif格式的图片还原后的清晰度损失较大,因此进行了进一步优化处理。
为解决这一问题,将边缘检测函数最后裁剪获得新图片宽和高的参数,进行区别赋值,定义全局变量SIZE来控制。
if ‘.tif’ in file:
SIZE=1350
else:
SIZE=140
三、结果
剩余不一一上传,如图
四、代码
具体代码见具体代码
来源:CSDN
作者:GUANYX~
链接:https://blog.csdn.net/gyx1549624673/article/details/103802574