2016-05-30 10 views
2

Ich versuche Schärfen Faltung Matrixfilter für Bild zu implementieren.Für dies ich Matrix 3x3 erstellen. Vielleicht habe ich etwas falsch mit der Formel gemacht? Auch ich habe versucht, andere schärfen Matrix, aber es hat nicht geholfen. Der Farbwert könnte größer als 255 oder kleiner als Null sein, daher entscheide ich mich, einige Grenzen zu setzen (0 255). Ist es die richtige Lösung?Faltung Matrix schärfen Filter

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

einige definieren

#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) 

und Algorithmus

- (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; 
} 

Als Ergebnis habe ich diese this

+1

"Vielleicht habe ich mit der Formel etwas falsch gemacht?" - Nicht sicher. Hast du diesen Effekt nicht vor? Ich denke, es sieht ziemlich - interessant aus. Wie auch immer, Spam-Tags nicht spammen! – Olaf

+1

Schneiden Sie die Farbwerte nicht nur an Ihre Grenzen, sondern skalieren Sie sie. Mit der gegebenen Matrix können Sie Werte in einem Bereich von -2040 bis 2295 erhalten. Wenn Sie dies und die Tatsache, dass alle Farbwerte zwischen 0 und 255 liegen können, können Sie diese Formel verwenden, um die Werte zu skalieren und so die Menge an Information zu erhalten: ' y = (x + 2040)/(2295 + 2040) * (255 - 0) + 0', wobei 'x' die gefilterten Werte und' y' der neue Farbwert zwischen 0 und 255 sind. (Allgemeines Format zum Konvertieren von x von [a, b] nach y in [c, d] ist "y = (x - a)/(ba) * (dc) + c)') – muXXmit2X

+0

@Olaf Es wird angenommen, dass der Effekt "schärfen" :(I Diese Tags hinzugefügt, weil es ein wenig c und C++. Sorry über das. –

Antwort

1

Betrachten Sie diese Punkte sind in der Mitte des Bildes:

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

Da Sie Bild anstelle aktualisieren, das ist, wie es irgendwo in der Mitte des Zyklus sharpen aussieht:

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

Wo u steht für aktualisierte Pixel, c für Strom. Seine neue Farbe hängt also von der Farbe der Surround-Pixel ab, von denen die Hälfte aus bereits geschärftem Bild, die andere Hälfte aus dem Ursprung stammt. Um es zu beheben benötigen wir eine Kopie des Originalbildes des Pixels:

... 
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++) { 
... 

Und jetzt brauchen wir nur eine Zeile ändern unsere aktuellen Pixel aus dem Originalbild zu erhalten

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

Here are some Beispiele dafür, wie es funktioniert im Vergleich zu nicht aktualisiertem Filter (Link ist Dropbox, tut mir leid). Ich habe verschiedene Matrices versucht, und für mich als das Beste war irgendwo um

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

Auch muss ich feststellen, dass diese Art und Weise Originalbild zu halten nicht optimal ist. Mein Fix verdoppelt im Grunde die Menge des verbrauchten Speichers. Es könnte leicht gemacht werden, indem nur zwei Pixelzeilen gehalten werden, und ich bin mir sicher, dass es noch bessere Möglichkeiten gibt.