2016-05-30 107 views
2

我試圖爲圖像實現銳化卷積矩陣濾波器。爲此我創建矩陣3x3。也許我做了錯誤的公式嗎?我也試過其他銳化矩陣,但它沒有幫助。顏色值可能大於255或小於0,所以我決定給這個限制(0 255)。這是否正確?卷積矩陣銳化濾波器

static const int filterSmallMatrixSize = 3; 
static const int sharpMatrix[3][3] = {{-1, -1, -1},{-1, 9, -1},{-1, -1, -1}}; 

一些限定

#define Mask8(x) ((x) & 0xFF) 
#define R(x) (Mask8(x)) 
#define G(x) (Mask8(x >> 8)) 
#define B(x) (Mask8(x >> 16)) 
#define A(x) (Mask8(x >> 24)) 
#define RGBAMake(r, g, b, a) (Mask8(r) | Mask8(g) << 8 | Mask8(b) << 16 | Mask8(a) << 24) 

和算法

- (UIImage *)processSharpFilterUsingPixels:(UIImage *)inputImage 
{ 
    UInt32 *inputPixels; 
    CGImageRef inputCGImage = [inputImage CGImage]; 
    NSUInteger inputWidth = CGImageGetWidth(inputCGImage); 
    NSUInteger inputHeight = CGImageGetHeight(inputCGImage); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    NSUInteger bytesPerPixel = 4; 
    NSUInteger bitsPerComponent = 8; 
    NSUInteger inputBytesPerRow = bytesPerPixel * inputWidth; 
    inputPixels = (UInt32 *)calloc(inputHeight * inputWidth, sizeof(UInt32)); 
    CGContextRef context = CGBitmapContextCreate(inputPixels, inputWidth, inputHeight, 
               bitsPerComponent, inputBytesPerRow, colorSpace, 
               kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 
    CGContextDrawImage(context, CGRectMake(0, 0, inputWidth, inputHeight), inputCGImage); 

    for (NSUInteger j = 1; j < inputHeight - 1; j++) 
    { 
     for (NSUInteger i = 1; i < inputWidth - 1; i++) 
     { 
      Float32 newRedColor = 0; 
      Float32 newGreenColor = 0; 
      Float32 newBlueColor = 0; 
      Float32 newA = 0; 

      for (int filterMatrixI = 0 ; filterMatrixI < filterSmallMatrixSize ; filterMatrixI ++) 
      { 
       for (int filterMatrixJ = 0; filterMatrixJ < filterSmallMatrixSize; filterMatrixJ ++) 
       { 
        UInt32 * currentPixel = inputPixels + ((j + filterMatrixJ - 1) * inputWidth) + i + filterMatrixI - 1; 
        int color = *currentPixel; 
        newRedColor += (R(color) * sharpMatrix[filterMatrixI][filterMatrixJ]); 
        newGreenColor += (G(color) * sharpMatrix[filterMatrixI][filterMatrixJ]); 
        newBlueColor += (B(color)* sharpMatrix[filterMatrixI][filterMatrixJ]); 
        newA += (A(color) * sharpMatrix[filterMatrixI][filterMatrixJ]); 
       } 
      } 
      int r = MAX(MIN((int)newRedColor,255), 0); 
      int g = MAX(MIN((int)newGreenColor,255), 0); 
      int b = MAX(MIN((int)newBlueColor,255), 0); 
      int a = MAX(MIN((int)newA,255), 0); 
      UInt32 *currentMainImagePixel = inputPixels + (j * inputWidth) + i; 
      *currentMainImagePixel = RGBAMake(r,g,b,a); 
     } 
    } 

    CGImageRef newCGImage = CGBitmapContextCreateImage(context); 
    UIImage * processedImage = [UIImage imageWithCGImage:newCGImage]; 

    CGColorSpaceRelease(colorSpace); 
    CGContextRelease(context); 
    free(inputPixels); 

    return processedImage; 
} 

作爲結果我有此this

+1

「也許我在配方中做了錯誤?」 - 不確定。你不打算這種效果嗎?我認爲它看起來很有趣。無論如何,不​​要垃圾語言標籤! – Olaf

+1

不要只將顏色值剪裁到你的邊界,而是將它們縮放。使用給定的矩陣,您可以獲得從-2040到2295範圍內的值。瞭解了這一點以及所有顏色值可以介於0和255之間的事實,您可以使用該公式來縮放值,從而保留信息量: y =(x + 2040)/(2295 + 2040)*(255-0)+ 0',其中'x'是濾波後的值,'y'是您在0到255之間的新顏色值。從[a,b]到[c,d]中的y是'y =(x-a)/(ba)*(dc)+ c)') – muXXmit2X

+0

@Olaf它假設是「銳化」添加這個標籤,因爲它有點c和C++。對不起,關於這個。 –

回答

1

考慮這些是在圖像的中間像素:

|_|_|_|_| 
|_|_|_|_| 
|_|_|_|_| 
|_|_|_|_| 

既然你正在更新到位的形象,這是它的外觀在磨礪週期的中間位置:

|u|u|u|u| 
|u|u|u|u| 
|u|c|_|_| 
|_|_|_|_| 

u代表更新像素,c電流。所以他的新顏色取決於環繞像素的顏色,其中一半來自已經銳化的圖像,一半來自原點。爲了解決這個問題,我們需要原始圖像的像素的副本:

... 
CGContextDrawImage(context, CGRectMake(0, 0, inputWidth, inputHeight), inputCGImage); 

UInt32 *origPixels = calloc(inputHeight * inputWidth, sizeof(UInt32)); 
memcpy(origPixels, inputPixels, inputHeight * inputWidth * sizeof(UInt32)); 

for (NSUInteger j = 1; j < inputHeight - 1; j++) { 
... 

現在,我們只需要改變一行從原始圖像得到我們的關注像素的運行方式相比

//changed inputPixels -> origPixels 
UInt32 * currentPixel = origPixels + ((j + filterMatrixJ - 1) * inputWidth) + i + filterMatrixI - 1; 

Here are some例子沒有更新過濾器(鏈接是保管箱,對此感到抱歉)。我已經嘗試了不同的矩陣,對我來說最好的是大約

const float sharpMatrix[3][3] = {{-0.3, -0.3, -0.3},{-0.3, 3.4, -0.3},{-0.3, -0.3, -0.3}} 

而且,我需要注意,保持原始圖像的這種方式是不是最優的地方。我的修復程序基本上使內存消耗量增加了一倍。通過僅保留兩行像素就可以輕鬆完成,我相信還有更好的方法。