卷积矩阵锐化滤波器

Convolution matrix sharpen filter

我正在尝试为 image.For 实现锐化卷积矩阵滤波器,我创建了 3x3 矩阵。也许我在公式上做错了什么?我也尝试了其他锐化矩阵,但没有帮助。颜色值可能大于 255 或小于零,所以我决定对此 (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;
}

结果我有了这个

考虑这些是图像中间的像素:

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

由于您正在就地更新图像,因此它在锐化周期中间某处看起来是这样的:

|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 与未更新过滤器相比如何工作的示例(link 是保管箱,对此感到抱歉)。我尝试了不同的矩阵,对我来说最好的是

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

此外,我需要注意的是,这种保留原始图像的方式并不是最优的。我的修复基本上使消耗的内存量加倍。只需保留两行像素即可轻松完成,我相信还有更好的方法。