Адаптивный порог 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
фильтр основного изображения