一、題目
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)對合成後圖像進行邊緣檢測,然後裁剪去除周圍白色、黑色或其他異常顔色的邊框。
擷取圖檔,轉換灰階
提取圖像的梯度:以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
三、結果
剩餘不一一上傳,如圖
四、代碼
具體代碼見具體代碼