Адаптивный порог CIKernel/CIFilter iOS

Я исследовал все, чтобы найти ядро, которое выполняет адаптивный порог на iOS. К сожалению, я не понимаю язык ядра или его логику. Ниже я нашел подпрограмму, которая выполняет пороговое значение ( https://gist.github.com/xhruso00/a3f8a9c8ae7e33b8b23d)

static NSString * const kKernelSource = @"kernel vec4 thresholdKernel(sampler image)\n"
"{\n"
"  float inputThreshold = 0.05;\n"
"  float pass = 1.0;\n"
"  float fail = 0.0;\n"
"  const vec4   vec_Y = vec4( 0.299, 0.587, 0.114, 0.0 );\n"
"  vec4  src = unpremultiply( sample(image, samplerCoord(image)) );\n"
"  float Y = dot( src, vec_Y );\n"
"  src.rgb = vec3( compare( Y - inputThreshold, fail, pass));\n"
"  return premultiply(src);\n"
"}";

Можно ли переписать это в адаптивное ядро ​​порога? Изображение, которое я передаю ему, было превращено в черно-белое и уже размыто. Есть ли ресурсы, на которые вы могли бы указать мне? Я хотел бы придерживаться CoreImage, поскольку весь мой стек построен вокруг него.

Изменить: лучший пример / ссылка из того, что я пытаюсь достичь, была реализована в GPUImageAdaptiveThresholdFilter GPUImage - https://github.com/BradLarson/GPUImage/blob/c5f0914152419437869c35e29858773b1a06083c/framework/Source/GPUImageAdaptiveThresholdFilter.m

2 ответа

Решение

Фильтр Саймона - это правильный подход для достижения желаемого эффекта, однако вам нужно изменить пару вещей.

Прежде всего, поменяйте порядок imageLuma а также thresholdLuma, поскольку мы хотим, чтобы черные буквы оставались черными, а не наоборот. Кроме того, вы должны добавить константу (я выбрал 0.01) убрать шум.

    var thresholdKernel =  CIColorKernel(string:
    "kernel vec4 thresholdFilter(__sample image, __sample threshold)" +
        "{" +
        "   float imageLuma = dot(image.rgb, vec3(0.2126, 0.7152, 0.0722));" +
        "   float thresholdLuma = dot(threshold.rgb, vec3(0.2126, 0.7152, 0.0722));" +
        "   return vec4(vec3(step(thresholdLuma, imageLuma+0.001)), 1);"     
    "}"

override var outputImage: CIImage! {
    guard let inputImage = inputImage,
        let thresholdKernel = thresholdKernel else {
        return nil
    }
    let blurred = inputImage.applyingFilter("CIBoxBlur", withInputParameters: [kCIInputRadiusKey: 5]) // block size
    let extent = inputImage.extent
    let arguments = [inputImage, blurred]
    return thresholdKernel.apply(withExtent: extent, arguments: arguments)
}

И это то, что вы получаете, только используя Apple Core Image, без необходимости устанавливать какие-либо внешние библиотеки:)

Конечно, вы можете немного поиграться со значениями константы и размера блока.

Как это выглядит: я использовал CoreImage CIBoxBlur (хотя выделенные фильтры свертки могут быть быстрее) и передал результат этого в мой существующий пороговый фильтр.

class AdaptiveThresholdFilter: CIFilter
{
    var inputImage : CIImage?


    var thresholdKernel =  CIColorKernel(string:
    "kernel vec4 thresholdFilter(__sample image, __sample threshold)" +
    "{" +
    "   float imageLuma = dot(image.rgb, vec3(0.2126, 0.7152, 0.0722));" +
    "   float thresholdLuma = dot(threshold.rgb, vec3(0.2126, 0.7152, 0.0722));" +

    "   return vec4(vec3(step(imageLuma, thresholdLuma)), 1.0);" +
    "}"
    )


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

        let blurred = inputImage.imageByApplyingFilter("CIBoxBlur",
               withInputParameters: [kCIInputRadiusKey: 9])

        let extent = inputImage.extent
        let arguments = [inputImage, blurred]

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

Я нашел это изображение затененной страницы и с этим кодом:

let page = CIImage(image: UIImage(named: "son1.gif")!)

let filter = AdaptiveThresholdFilter()

filter.inputImage = page

let final = filter.outputImage

Я получил этот результат:

Ура!

Саймон

Вы можете использовать CIColorThresholdOtsu фильтр основного изображения

Другие вопросы по тегам