2008-11-18 142 views
13

縮放2D圖像數組的最佳方式是什麼?例如,假設我有一個1024 x 2048字節的圖像,每個字節都是一個像素。每個像素都是從0到255的灰度級別。我希望能夠通過任意因子縮放此圖像並獲取新圖像。所以,如果我將圖像縮放0.68倍,我應該得到一個尺寸爲0.68 * 1024 x 0.68 * 2048的新圖像。一些像素將相互摺疊。而且,如果我按照3.15的係數進行縮放,則會得到像素重複的較大圖像。那麼,完成這個的最好方法是什麼?C/C++中的圖像縮放和旋轉

接下來,我想能夠以0到360度(0 - 2Pi)範圍內的任意角度旋轉圖像。旋轉後裁剪圖像不是問題。什麼是最好的方法來做到這一點?

回答

10

沒有「簡單」的表達方式。縮放和旋轉都不是"trivial" procesis.

谷歌它爲2d圖像庫。 Magick++可以作爲divideandconquer.se點的想法,但也有其他。

8

你想自己做骯髒的工作還是可以ImageMagick爲你做?

12

有很多方法可以縮放和旋轉圖像。規模最簡單的方法是:

dest[dx,dy] = src[dx*src_width/dest_width,dy*src_height/dest_height] 

但這種增加細節的規模和損失時,減少大小時產生塊狀效應。有許多方法可以產生更好的效果,例如bilinear filtering

爲了旋轉,將src像素位置可被使用a rotation matrix計算:

sx,sy = M(dx,dy) 

其中M是該目的地像素映射到源圖像的矩陣。再次,你需要做插值來產生非塊狀結果。

但是如果你不想進入圖像處理的數學,有很多庫可用。

3

複製或丟棄像素不是最好的方法或圖像調整大小,因爲結果將顯示像素化和鋸齒狀。爲了獲得最佳效果,您應該重新取樣圖像,這將使得生成的圖像看起來更平滑。有很多重採樣方法,比如雙線性,雙三次,lanczos等。

看看wxWidgets的BicubicResample函數。它適用於各種圖像,不僅是灰度,而且應該能夠適應您的需求。然後還有重新採樣代碼from VirtualDub。 Google Codesearch可能會顯示更多相關的代碼。

編輯:鏈接在預覽中看起來不錯,但在發佈時會被破壞。這很奇怪。轉到谷歌codesearch和分別查詢「wxwidgets resamplebicubic」和「virtualdub resample」以獲得相同的結果。

9

你正在做的是將一組輸入點映射到一組輸出點。問題的第一部分是確定調整大小或旋轉的映射;第二部分是處理不完全位於像素邊界上的點。

映射爲resize很簡單:

x' = x * (width'/width) 
y' = y * (height'/height) 

映射旋轉只是有點困難。

x' = x * cos(a) + y * sin(a) 
y' = y * cos(a) - x * sin(a) 

確定離開網格的像素值的技術稱爲插值。有許多這樣的算法,在速度和最終圖像質量方面廣泛。其中一些質量/時間的順序是最近鄰,雙線性,雙三次和Sinc濾波器。

2

CxImage是一個免費的圖庫處理圖像,它可以做你想做的。 我沒有親自使用它,除了微不足道的東西,但我已經看到它反覆推薦。

+0

雖然這在理論上可以回答這個問題,[但最好(// meta.stackoverflow .com/q/8259)在這裏包括答案的基本部分,並提供供參考的鏈接。 – 2016-08-31 13:43:36

0
point scaling(point p,float sx,float sy) { 
    point s; 

    int c[1][3]; 
    int a[1][3]={p.x,p.y,1}; 
    int b[3][3]={sx,0,0,0,sy,0,0,0,1}; 

    multmat(a,b,c); 

    s.x=c[0][0]; 
    s.y=c[0][1]; 

    return s; 
} 
0

CxImage調整大小方法會產生奇怪的結果。我使用Resample和Resample2函數以及具有相同結果的插值方法的所有可用變體。例如,嘗試調整大小爲1024 x 768的1024 x 768圖像並將其填充爲白色。您會發現圖像上有像素顏色不同變爲白色!您可以選中此項:在Windows Paint中打開調整大小的圖像,然後嘗試用黑色填充它。結果肯定會讓你感到愉快。

0

查看Intel Performance Primitives。我之前使用過它,它在x86上產生接近最佳性能。還有一個測試程序,可以使用各種算法。

+0

雖然這可能在理論上回答這個問題,但[這將是更可取的](// meta.stackoverflow.com/q/8259)在這裏包含答案的基本部分,並提供供參考的鏈接。 – 2016-08-31 13:43:01

2

它還沒有被提及,所以我會指出OpenCV具有縮放和旋轉圖像的功能,以及大量的其他實用程序。 它可能包含許多與問題無關的功能,但它很容易設置和使用該類型的庫。

您可以嘗試手動實現這種轉換,但縮放和旋轉的簡單方法通常會導致明顯的細節丟失。

使用OpenCV的,縮放可以做到像這樣:

float scaleFactor = 0.68f; 
cv::Mat original = cv::imread(path); 
cv::Mat scaled; 
cv::resize(original, scaled, cv::Size(0, 0), scaleFactor, scaleFactor, cv::INTER_LANCZOS4); 
cv::imwrite("new_image.jpg", scaled); 

這通過使用蘭克澤斯插值的0.68係數調整圖像下移。

我不太熟悉旋轉,但這裏是OpenCV網站上的一個教程中的一個示例的一部分,我已將其編輯到相關部分。 (原來有歪斜和翻譯也...)

/// Compute a rotation matrix with respect to the center of the image 
Point center = Point(original.size().width/2, original.size().height/2); 
double angle = -50.0; 
double scale = 0.6; 

/// Get the rotation matrix with the specifications above 
Mat rot_mat(2, 3, CV_32FC1); 
rot_mat = getRotationMatrix2D(center, angle, scale); 

/// Rotate the image 
Mat rotated_image; 
warpAffine(src, rotated_image, rot_mat, src.size()); 

OpenCV Website

They have some very nice documentation too.

+0

好點。我已經添加了一些例子,所以現在更多的是真正的答案。 – Meta 2016-08-31 13:31:04