仿射變換及坐標變換公式
幾何變換改進圖像中像素間的空間關系。這些變換通常稱為橡皮模變換,因為它們可看成是在一塊橡皮模上印刷一幅圖像,然后根據預定的一組規則拉伸該薄膜。在數字圖像處理中,幾何變換由兩個基本操作組成:
(1)坐標的空間變換
(2)灰度內插,即對變換后的像素賦灰度值
坐標變換公式
(x,y) = T{(v, w)}
其中,(v, w)是原圖像中像素的坐標,(x, y)是變換后圖像中像素的坐標。最常用的空間坐標變換之一是仿射變換
基於上式的仿射變換公式
實際上,我們可以用兩種方法來使用上式。第一種方法稱為向前映射,它由掃描輸入圖像的像素,並在每個位置(v, w)用上式直接計算輸出圖像中相應像素的空間位置(x, y)組成。向前映射算法的一個問題是輸入圖像中的兩個或更多個像素可被變換到輸出圖像的同一位置,這就產生了如何把多個輸出值合並到一個輸出像素的問題。第二種方法,反向映射,掃描輸出像素的位置,並在每一個位置(x, y)使用(v, w) = T-1(x, y)計算輸入圖像中的相應位置。然后通過內插決定輸出像素的灰度值。本篇文章使用反向映射。
<以上基礎知識來源於 《數字圖像處理》岡薩雷斯 P50-P51 讀者可自行查閱>
在上一篇文章中,主要是圖片的放大與縮小,在灰度內插的過程中也涉及到目標圖像到原圖像的坐標變換,代碼如下
1 void bilinera_interpolation(short** in_array, short height, short width, 2 short** out_array, short out_height, short out_width) 3 { 4 double h_times = (double)out_height / (double)height, 5 w_times = (double)out_width / (double)width; 6 short x1, y1, x2, y2, f11, f12, f21, f22; 7 double x, y; 8 9 for (int i = 0; i < out_height; i++){ 10 for (int j = 0; j < out_width; j++){ 11 x = j / w_times; 12 y = i / h_times; 13 x1 = (short)(x - 1); 14 x2 = (short)(x + 1); 15 y1 = (short)(y + 1); 16 y2 = (short)(y - 1); 17 f11 = is_in_array(x1, y1, height, width) ? in_array[y1][x1] : 0; 18 f12 = is_in_array(x1, y2, height, width) ? in_array[y2][x1] : 0; 19 f21 = is_in_array(x2, y1, height, width) ? in_array[y1][x2] : 0; 20 f22 = is_in_array(x2, y2, height, width) ? in_array[y2][x2] : 0; 21 out_array[i][j] = (short)(((f11 * (x2 - x) * (y2 - y)) + 22 (f21 * (x - x1) * (y2 - y)) + 23 (f12 * (x2 - x) * (y - y1)) + 24 (f22 * (x - x1) * (y - y1))) / ((x2 - x1) * (y2 - y1))); 25 } 26 } 27 }
其中,第11,12行為目標圖像到原圖像的坐標變換,接下來根據仿射變換公式對圖像做進一步處理
水平偏移變換
水平偏移變換公式為
x = v
y = Sh * v + w
反解上述公式得
v = x
w = y - Sh * v
結果為目標圖像到原圖像的坐標變換,令Sh = 0.5,並對應用到上述代碼11,12行,同時將圖像擴大到2800*1280,結果為
旋轉變換
旋轉變換公式
x = vcosθ - wsinθ
y = vsinθ + wcosθ
令θ = ∏/4,反解得
v = x/√2 + y/√2
w = y/√2 - x/√2
將圖像擴大為2000*2000,但是這個時候得到的圖像為
為了解決這一問題,使旋轉后的圖像位於中央,我將所得圖片右移m_w, 下移m_h,則公式變為
x = vcosθ - wsinθ + m_w
y = vsinθ + wcosθ + m_h
令θ = ∏/4,反解得
v = (x + y - m_h - m_w)/√2
w = (y - x - m_h + m_w)/√2
結果為
其余變換原理基本相同,因此不再進行演示