2013-01-12 107 views
0

我希望寫出來可能有助於解決我的問題。我擁有包含臉部的圖像,並且我想重新拍攝這些圖像,尊重縱橫比,同時保持儘可能多的臉部。在不刪除指定部分的情況下裁剪圖像的算法

我想將圖像裁剪爲任意矩形,該矩形可以是高,短,方或任何高達4:1方面的任何矩形。儘可能多的,我想避免剪出我指定的臉部或特徵(作爲圖像矩形的內部矩形)。例如。我有一個(0,0,500,300)的圖像矩形和一個(20,40,75,75)的特徵矩形,我想將它裁剪(考慮其長寬比)爲一個矩形(0,0,320,200 ),同時最小限度地裁剪臉部矩形。

我有一箇中心裁剪的工作實現,其中我確定圖像較大的一面,並根據相同的比例縮放另一面,將x和y設置爲縮放w/h的中心 - 目標w/h 。

爲了清楚起見,簽名會是這個樣子(中的OBJ-C):

(CGRect)crop:(CGSize)sourceSize toFitSize:(CGSize)fitSize withoutCroppingRect:(CGRect)featuresRect 

哪裏sourceSize是原始圖像的大小,fitSize是我要裁剪的圖像轉換成的形狀,和featuresRect是一個矩形,在(0,0,sourceSize.width, sourceSize,height)的範圍內。

也許這應該作爲一個「中心作物」,以特徵矩形爲中心?試圖圍繞這甚至意味着什麼。

+0

由於500/300!= 300/200,您不能在保留寬高比的同時裁剪圖像矩形(0,0,500,300)到(0,0,300,200)。 - 如果「特徵矩形」不適合目標矩形,會發生什麼? –

+0

@MartinR好點,我剛纔輸入的很快。我想這個算法不需要完全遵守特徵矩形,但是需要盡其最大的努力。這是問題的一部分;) – akaru

+0

也許如果你告訴我們你實際想要完成的是什麼,而不是你試圖完成它的方式,我們可以提出一些建議。現在,你寫的所有內容都很模糊,可能會有無數的答案。如果「特徵矩形」通常包含一個面,則將特徵矩形的中心落在[1/3行](http:// en。wikipedia.org/wiki/Rule_of_thirds),以產生一個令人滿意的結果。或者,如果你願意,在[黃金比例線](http://en.wikipedia.org/wiki/Golden_ratio#Aesthetics) – user1118321

回答

0

有了這個,我認爲它是做你想做的,或者至少它在正確的方向推動你。輸出矩形保持與源圖像矩形相同的寬高比。

用法示例:

CGRect sizedRect = [self cropSize:self.inputView.image.size 
         toFitSize:self.outputView.bounds.size 
       withoutCroppingRect:self.regionOfInterest.frame]; 

CGImageRef cgImage = self.inputView.image.CGImage; 

CGImageRef cgCroppedImage = CGImageCreateWithImageInRect (
             cgImage, 
             sizedRect 
             ); 

self.outputView.image = [UIImage imageWithCGImage:cgCroppedImage]; 

有一些的,你將不得不考慮,在具體問題:
- 您返回矩形可能比fitSize大,因爲它不會作物featuresRect,所以你可能需要檢查這個並在應用裁剪之後縮放圖像(或者適當地設置你的輸出imageView的scaleToFit)。
- 你從哪裏獲得你的ROI幀數據?它是相對於原始源圖像還是相對於包含源圖像的imageView。如果是後者,您需要確保源圖像的大小爲1:1,因爲它的imageView是作用於圖像的,而不是imageView。
- 輸出imageView小於輸入imageView。我不確定它會如何變大,但它可能會引入類似的縮放問題。
- 您將需要添加被零除錯誤檢查。

-  (CGRect)cropSize:(CGSize)sourceSize 
      toFitSize:(CGSize)fitSize 
    withoutCroppingRect:(CGRect)featuresRect 
{ 
    CGRect result = CGRectZero; 
    BOOL fitSizeIsTaller; 
    CGFloat sourceRatio = sourceSize.width/sourceSize.height; 
    CGFloat fitRatio = fitSize.width /fitSize.height; 
    if (sourceRatio > fitRatio) 
      fitSizeIsTaller = YES; 
    else fitSizeIsTaller = NO; 

     //size sourceRect to fitSize 
    if (fitSizeIsTaller){ 
     result.size.width = fitSize.width; 
     result.size.height = result.size.width/sourceRatio; 
    } else { 
     result.size.height = fitSize.height; 
     result.size.width = result.size.height * sourceRatio; 
    } 
     //make sure it is at least as large as fitSize 
    if (result.size.height < featuresRect.size.height) { 
     result.size.height = featuresRect.size.height; 
     result.size.width = result.size.height * sourceRatio; 
    } 

    if (result.size.width < featuresRect.size.width) { 
     result.size.width = featuresRect.size.width; 
     result.size.height = result.size.width/sourceRatio; 
    } 

      //locate resultRect in center 
    result.origin.x = (sourceSize.width - result.size.width)/2; 
    result.origin.y = (sourceSize.height - result.size.height)/2; 

      //shift origin of result to make sure it includes ROI 

    if (featuresRect.origin.x < result.origin.x) //shift right? 
       result.origin.x = featuresRect.origin.x; 
    else 
     if ((featuresRect.origin.x + featuresRect.size.width) 
       > (result.origin.x + result.size.width)) //shift left? 
      result.origin.x = (featuresRect.origin.x + featuresRect.size.width) 
          - result.size.width; 

    if (featuresRect.origin.y < result.origin.y) //shift up? 
       result.origin.y = featuresRect.origin.y; 
    else 
     if ((featuresRect.origin.y + featuresRect.size.height) 
       > (result.origin.y + result.size.height)) //shift down? 
      result.origin.y = (featuresRect.origin.y+featuresRect.size.height) 
          - result.size.height; 
    return result; 
} 
+0

投資回報率與實際形象有關。現在只需使用該區域的人臉檢測。我會檢查一下 - 我相信它至少會指向正確的方向。 – akaru

相關問題