2016-03-29 2 views

Répondre

6

Vous devez écrire votre propre en utilisant Core Image noyau Langue et CIColorKernel.

J'utiliserais un smoothstep et passerais deux valeurs de bord avec la luminance du pixel courant. Le CIKL pourrait ressembler à ceci:

kernel vec4 color(__sample pixel, float inputEdgeO, float inputEdge1) 
{ 
    float luma = dot(pixel.rgb, vec3(0.2126, 0.7152, 0.0722)); 
    float threshold = smoothstep(inputEdgeO, inputEdge1, luma); 
    return vec4(threshold, threshold, threshold, 1.0); 
} 

Vous pouvez envelopper cela dans un CIFilter avec le code suivant:

class SmoothThreshold: CIFilter 
{ 
    var inputImage : CIImage? 
    var inputEdgeO: CGFloat = 0.25 
    var inputEdge1: CGFloat = 0.75 

    var colorKernel = CIColorKernel(string: 
     "kernel vec4 color(__sample pixel, float inputEdgeO, float inputEdge1)" + 
     "{" + 
     " float luma = dot(pixel.rgb, vec3(0.2126, 0.7152, 0.0722));" + 
     " float threshold = smoothstep(inputEdgeO, inputEdge1, luma);" + 
     " return vec4(threshold, threshold, threshold, 1.0);" + 
     "}" 
    ) 

    override var outputImage: CIImage! 
    { 
     guard let inputImage = inputImage, 
      colorKernel = colorKernel else 
     { 
      return nil 
     } 

     let extent = inputImage.extent 
     let arguments = [inputImage, 
         inputEdgeO, 
         inputEdge1] 

     return colorKernel.applyWithExtent(extent, 
              arguments: arguments) 
    } 
} 

Notez que vous devez vous assurer inputEdge0 est inférieure à inputEdge1, ou smoothstep ira un peu fou. Vous pouvez les saturate aussi, pour assurer qu'ils sont entre 0 et 1.

Jetez un oeil à CIFilter.registerFilterName qui vous permettra de créer une instance de SmoothThreshold avec la syntaxe familière, bien que cela fonctionne très bien:

let image = CIImage(image: UIImage(named: "monalisa.jpg")!)! 

let filter = SmoothThreshold() 
filter.inputImage = image 

let final = filter.outputImage 

À la votre!

Simon

+0

Merci! J'étais surtout intéressé par l'algorithme puisque je suis familier avec la création de noyaux. Pourquoi comparez-vous le canal luma? (Je ne suis intéressé qu'à comparer la moyenne des valeurs RGB mais je suis toujours curieux quant à la raison derrière luma). – joelg

+1

Dépend du cas d'utilisation: si le seuil est défini par la luminosité perçue, le calcul de la moyenne n'est pas tout à fait correct. Le vert pur (0,1,0) est beaucoup plus clair que le bleu pur (0,0,1) mais a les mêmes valeurs moyennes. –

+0

Ouais, c'est tout à fait logique. À la fin de la journée, j'essayais juste d'accomplir ce qui est décrit ici: https://www.filterforge.com/wiki/index.php/Thresholds#Interpolation_.28.22Blending.22.29 – joelg

1

Cela a fini par travailler pour moi:

[CIColorKernel kernelWithString: 
       @"kernel vec4 threshold(__sample s, float thresh) {\n" 
       "float avg = (s.r + s.g + s.b)/3.0;\n" 
       "float val = smoothstep(0.0, thresh, avg);" 
       "return vec4(val, val, val, 1.0);\n}"];