代码之家  ›  专栏  ›  技术社区  ›  Oscar Apeland

从具有核心图像的查找图像中筛选图像

  •  3
  • Oscar Apeland  · 技术社区  · 8 年前

    我正在为我的应用程序中的图像开发一些颜色过滤器。我们使用查找图像,因为它们易于从其他程序中复制过滤器,并且便于跨平台获得相同的结果。我们的查找看起来像这样

    以前,我们使用了 gpuimage 来过滤查找图像,但是我想避免这种依赖性,因为它是一个巨大的5.4MB,我们只需要这一个功能。

    搜索了几个小时后,我似乎找不到任何资源来说明如何使用查找图像通过 coreimage>筛选图像。但是,查看文档, cicolormatrix looks like the proper tool.这里的问题是我太笨了,不明白这是怎么回事。这让我想到了我的问题;

    是否有人有一个如何使用 cicolormatrix 从查找中筛选图像的示例?(或任何关于我应该如何着手解决问题的提示)

    我已经刮掉了 gpuimage s code,看起来他们用来从查找图像中过滤的着色器定义如下:

    查找图像明暗器:

    varying vec2 texturecoordinate;
    可变的vec2纹理坐标2;
    均匀采样器2d输入图像纹理;
    均匀采样器2d输入图像纹理2;
    
    //查找纹理均匀浮动强度;
    空主()。{
    vec4 texturecolor=texture2d(输入图像纹理,纹理坐标);
    float bluecolor=texturecolor.b*63.0;
    
    vec2四芯1;
    quad1.y=地板(地板(蓝色)/8.0);
    quad1.x=地板(蓝色)-(quad1.y*8.0);
    
    矢量2 Quad2;
    quad2.y=地板(天花板(蓝色)/8.0);
    quad2.x=ceil(蓝色)-(quad2.y*8.0);
    
    vec2 texpos1;
    texpos1.x=(quad1.x*0.125)+0.5/512.0+((0.125-1.0/512.0)*纹理颜色.r);
    texpos1.y=(quad1.y*0.125)+0.5/512.0+((0.125-1.0/512.0)*纹理颜色.g);
    
    vec2 texpos2;
    texpos2.x=(quad2.x*0.125)+0.5/512.0+((0.125-1.0/512.0)*纹理颜色.r);
    texpos2.y=(quad2.y*0.125)+0.5/512.0+((0.125-1.0/512.0)*纹理颜色.g);
    
    vec4 newolor1=纹理2d(输入图像纹理2,texpos1);
    vec4 newolor2=纹理2d(输入图像纹理2,texpos2);
    vec4 newclor=混合(newclor1、newclor2、fract(bluecolor));
    
    gl_fragcolor=混合(texturecolor,vec4(newcolor.rgb,texturecolor.w),强度);
    }
    
    
    

    除了此顶点明暗器:

    attribute vec4 position;
    属性vec4 inputexturecoordinate;
    属性vec4 inputTextureCoordinate2;
    可变的vec2纹理坐标;
    可变的vec2纹理坐标2;
    
    空主()。{
    gl_position=位置;
    textureCoordinate=inputTextureCoordinate.xy;
    textureCoordinate2=inputTextureCoordinate2.xy;
    }
    
    
    

    我可以/应该使用这些明暗器创建自己的过滤器吗?

    enter image description here

    以前,我们用过GPUImage对于使用查找图像进行过滤,但是我想避免这种依赖性,因为它的容量高达5.4MB,我们只需要这一个功能。

    在搜索了几个小时后,我似乎找不到任何资源来说明如何使用查找图像来过滤图像槽。CoreImage.但是,看看这些文件,CIColorMatrix看起来是合适的工具。这里的问题是我太笨了,不明白这是怎么回事。这使我想到了我的问题;

    有人有使用的例子吗环磷酰胺从查找中筛选图像?(或任何关于我应该如何着手解决问题的建议)

    我刮了水槽G图像s代码,它们用于从查找图像中筛选的着色器的定义如下:

    查找图像明暗器:

    varying vec2 textureCoordinate;
    varying vec2 textureCoordinate2; 
    uniform sampler2D inputImageTexture; 
    uniform sampler2D inputImageTexture2;
    
     // lookup texture  uniform float intensity;  
     void main() {     
        vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); 
        float blueColor = textureColor.b * 63.0; 
    
        vec2 quad1;    
        quad1.y = floor(floor(blueColor) / 8.0);
        quad1.x = floor(blueColor) - (quad1.y * 8.0);
    
        vec2 quad2;
        quad2.y = floor(ceil(blueColor) / 8.0);
        quad2.x = ceil(blueColor) - (quad2.y * 8.0);
    
        vec2 texPos1;   
        texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
        texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 
    
        vec2 texPos2;     
        texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
        texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);          
    
        vec4 newColor1 = texture2D(inputImageTexture2, texPos1);   
        vec4 newColor2 = texture2D(inputImageTexture2, texPos2); 
        vec4 newColor = mix(newColor1, newColor2, fract(blueColor));   
    
        gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity);
    }
    

    除此顶点明暗器外:

    attribute vec4 position;
    attribute vec4 inputTextureCoordinate; 
    attribute vec4 inputTextureCoordinate2;
    varying vec2 textureCoordinate;
    varying vec2 textureCoordinate2;
    
    void main() {
        gl_Position = position;   
        textureCoordinate = inputTextureCoordinate.xy;     
        textureCoordinate2 = inputTextureCoordinate2.xy;
    }
    

    我可以/应该使用这些明暗器创建自己的过滤器吗?

    1 回复  |  直到 8 年前
        1
  •  0
  •   Oscar Apeland    8 年前

    这个答案的所有功劳都归Nghia Tran所有。如果你看到这个,谢谢!

    结果,一直以来只有一个答案。Nghia Tran写了一篇文章 here 他解决了我确切的用例。

    他很乐意提供一个扩展来生成 CIFilter 从一个查找图像,我将粘贴到下面,为将来的开发人员保留这个答案。

    您需要导入 CIFilter+LUT.h 如果你用的是斯威夫特。

    下面是一个演示如何在GPU上使用它的片段 斯威夫特4 .这离优化还很远,应该缓存上下文等,但这是一个很好的起点。

    static func applyFilter(with lookupImage: UIImage, to image: UIImage) -> UIImage? {
        guard let cgInputImage = image.cgImage else {
            return nil
        }
    
        guard let glContext = EAGLContext(api: .openGLES2) else {
            return nil
        }
    
        let ciContext = CIContext(eaglContext: glContext)
    
        guard let lookupFilter = CIFilter(lookupImage: lookupImage, dimension: 64) else {
            return nil
        }
    
        lookupFilter.setValue(CIImage(cgImage: cgInputImage),
                              forKey: "inputImage")
    
        guard let output = lookupFilter.outputImage else {
            return nil
        }
    
        guard let cgOutputImage = ciContext.createCGImage(output, from: output.extent) else {
            return nil
        }
    
        return UIImage(cgImage: cgOutputImage)
    }
    

    cifilter+lut.h过滤

    #import <CoreImage/CoreImage.h>
    @import UIKit.UIImage;
    
    @class CIFilter;
    
    @interface CIFilter (LUT)
    +(CIFilter *) filterWithLookupImage:(UIImage *)image dimension:(NSInteger) n;
    @end
    

    C滤波器+LUT.M

    #import "CIFilter+LUT.h"
    #import <CoreImage/CoreImage.h>
    #import <OpenGLES/EAGL.h>
    
    @implementation CIFilter (LUT)
    
    +(CIFilter *)filterWithLookupImage:(UIImage *)image dimension:(NSInteger)n {
        NSInteger width = CGImageGetWidth(image.CGImage);
        NSInteger height = CGImageGetHeight(image.CGImage);
        NSInteger rowNum = height / n;
        NSInteger columnNum = width / n;
    
        if ((width % n != 0) || (height % n != 0) || (rowNum * columnNum != n)) {
            NSLog(@"Invalid colorLUT");
            return nil;
        }
    
        unsigned char *bitmap = [self createRGBABitmapFromImage:image.CGImage];
    
        if (bitmap == NULL) {
            return nil;
        }
    
        NSInteger size = n * n * n * sizeof(float) * 4;
        float *data = malloc(size);
        int bitmapOffest = 0;
        int z = 0;
    
        for (int row = 0; row <  rowNum; row++) {
            for (int y = 0; y < n; y++) {
                int tmp = z;
                for (int col = 0; col < columnNum; col++) {
                    for (int x = 0; x < n; x++) {
                        float r = (unsigned int)bitmap[bitmapOffest];
                        float g = (unsigned int)bitmap[bitmapOffest + 1];
                        float b = (unsigned int)bitmap[bitmapOffest + 2];
                        float a = (unsigned int)bitmap[bitmapOffest + 3];
    
                        NSInteger dataOffset = (z*n*n + y*n + x) * 4;
    
                        data[dataOffset] = r / 255.0;
                        data[dataOffset + 1] = g / 255.0;
                        data[dataOffset + 2] = b / 255.0;
                        data[dataOffset + 3] = a / 255.0;
    
                        bitmapOffest += 4;
                    }
                    z++;
                }
                z = tmp;
            }
            z += columnNum;
        }
    
        free(bitmap);
    
        CIFilter *filter = [CIFilter filterWithName:@"CIColorCube"];
        [filter setValue:[NSData dataWithBytesNoCopy:data length:size freeWhenDone:YES] forKey:@"inputCubeData"];
        [filter setValue:[NSNumber numberWithInteger:n] forKey:@"inputCubeDimension"];
    
        return filter;
    }
    
    + (unsigned char *)createRGBABitmapFromImage:(CGImageRef)image {
        CGContextRef context = NULL;
        CGColorSpaceRef colorSpace;
        unsigned char *bitmap;
        NSInteger bitmapSize;
        NSInteger bytesPerRow;
    
        size_t width = CGImageGetWidth(image);
        size_t height = CGImageGetHeight(image);
    
        bytesPerRow = (width * 4);
        bitmapSize = (bytesPerRow * height);
    
        bitmap = malloc(bitmapSize);
        if (bitmap == NULL) {
            return NULL;
        }
    
        colorSpace = CGColorSpaceCreateDeviceRGB();
        if (colorSpace == NULL) {
            free(bitmap);
            return NULL;
        }
    
        context = CGBitmapContextCreate (bitmap, width,  height, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
        CGColorSpaceRelease(colorSpace);
    
        if (context == NULL) {
            free (bitmap);
        }
    
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
        CGContextRelease(context);
    
        return bitmap;
    }
    @end
    
    推荐文章