热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用CIfilter的误差扩散抖动图像

我正在尝试抖动图像。我编写了一些快速代码,这些代码应用了floydsteinberg抖动

我正在尝试抖动图像。我编写了一些快速代码,这些代码应用了floyd steinberg抖动,但是处理图像的时间很长,因为它没有包装在cifilter中,它只是快速代码。我在想,如果我可以创建自定义cifilter,它将在gpu上进行处理并加快处理速度。但是我不是CIfilter语言专家。

这是我的快速代码。为了清楚起见,我已将错误分布矩阵的计算完整写出。

internal struct color {
let r: Int
let g: Int
let b: Int
}
func ditherImage2(){
let image = UIImage(named: "image")
let width = Int(image!.size.width)
let height = Int(image!.size.height)
let pixelArray = pixelarray(image)
func offset(row: Int,column: Int) -> Int {
return row * width + column
}
for y in 0 .. for x in 0 .. let currentOffset = offset(row: y,column: x)
let currentColor = pixelArray![currentOffset]
// get current colour of pixel
let oldR = currentColor.r
let oldG = currentColor.g
let oldB = currentColor.b
// quantize / reduce the colours to pallet of 6 colours
let factor = 1;
let newR = round(factor * oldR / 255) * (255/factor)
let newG = round(factor * oldG / 255) * (255/factor)
let newB = round(factor * oldB / 255) * (255/factor)
pixelArray[currentOffset] = color(r:newR,g:newG,b:newB)
let errR = oldR - newR;
let errG = oldG - newG;
let errB = oldB - newB;
// distribute the error to the surrounding pixels using floyd stenberg matrix
let index = offset(row:x+1,column:y)
let c = pixelArray[index]
let r = c.r
let g = c.g
let b = c.b
r = r + errR * 7/16.0;
g = g + errG * 7/16.0;
b = b + errB * 7/16.0;
pixelArray[index] = color(r:r,g:g,b:b);
let index2 = offset(row:x-1,column:y+1 );
let c2 = pixelArray[index2]
let r2 = c.r
let g2 = c.g
let b2 = c.b
r2 = r2 + errR * 3/16.0;
g2 = g2 + errG * 3/16.0;
b2 = b2 + errB * 3/16.0;
pixelArray[index] = color(r:r2,g:g2,b:b2);
let index3 = offset(row:x,column:y+1);
let c3 = pixelArray[index3]
let r3 = c.r
let g3 = c.g
let b3 = c.b
r3 = r3 + errR * 5/16.0;
g3 = g3 + errG * 5/16.0;
b3 = b3 + errB * 5/16.0;
pixelArray[index] = color(r:r3,g:g3,b:b3);
let index4 = offset(row:x+1,column:y+1);
let c4 = pixelArray[index]
let r4 = c.r
let g4 = c.g
let b4 = c.b
r4 = r4 + errR * 1/16.0;
g4 = g4 + errG * 1/16.0;
b4 = b4 + errB * 1/16.0;
pixelArray[index] = color(r:r4,g:g4,b:b4);
}
}
}

我发现这个https://github.com/rhoeper/Filterpedia-Swift4包括一个用于有序抖动的自定义过滤器,我可以将其用作基础并尝试适应误差扩散抖动。我希望找到一个现有的自定义内核,该内核可以在开始学习CIfilter语言之前就可以完成工作。因此,我想知道是否有人拥有现有内核或指向该内核的链接?

有序抖动代码


  1. float orderedDither2x2(float colorin,float bx,float by,float errorIntensity)
    {
    float error = 0.0;
    int px = int(bx);
    int py = int(by);
    if (py == 0) {
    if (px == 0) { error = 1.0 / 4.0; }
    if (px == 1) { error = 3.0 / 4.0; }
    }
    if (py == 1) {
    if (px == 0) { error = 4.0 / 4.0; }
    if (px == 1) { error = 2.0 / 4.0; }
    }
    return colorin * (error * errorIntensity);
    }
    kernel vec4 ditherBayer(sampler image,float intensity,float matrix,float palette)
    {
    vec4 pixel = sample(image,samplerCoord(image));
    int msize = int(matrix);
    float px = mod(pixel.x,msize >= 5 ? float(4.0) : float(msize));
    float py = mod(pixel.y,msize >= 5 ? float(4.0) : float(msize));
    float red = pixel.r;
    float green = pixel.g;
    float blue = pixel.b;
    if (msize == 2) {
    pixel.r = orderedDither2x2(red,px,py,intensity);
    pixel.g = orderedDither2x2(green,intensity);
    pixel.b = orderedDither2x2(blue,intensity);
    }
    if (msize == 3) {
    pixel.r = orderedDither3x3(red,intensity);
    pixel.g = orderedDither3x3(green,intensity);
    pixel.b = orderedDither3x3(blue,intensity);
    }
    if (msize == 4) {
    pixel.r = orderedDither4x4(red,intensity);
    pixel.g = orderedDither4x4(green,intensity);
    pixel.b = orderedDither4x4(blue,intensity);
    }
    if (msize >= 5) {
    pixel.r = orderedDither8x8(red,intensity);
    pixel.g = orderedDither8x8(green,intensity);
    pixel.b = orderedDither8x8(blue,intensity);
    }
    if (int(palette) == 0) { return vec4(binary(vec3(pixel.r,pixel.g,pixel.b)),pixel.a); }
    if (int(palette) == 1) { return vec4(commodore64(vec3(pixel.r,pixel.a); }
    if (int(palette) == 2) { return vec4(vic20(vec3(pixel.r,pixel.a); }
    if (int(palette) == 3) { return vec4(appleII(vec3(pixel.r,pixel.a); }
    if (int(palette) == 4) { return vec4(zxSpectrumBright(vec3(pixel.r,pixel.a); }
    if (int(palette) == 5) { return vec4(zxSpectrumDim(vec3(pixel.r,pixel.a); }
    return pixel;
    }




弗洛伊德-斯坦伯格(Floyd-Steinberg)抖动的问题在于,它是一种串行算法-结果像素的颜色值取决于先前计算的像素。核心映像(以及任何类型的SIMD并行化技术)不适用于此类问题。它们旨在在所有像素上同时执行相同的任务。

但是,我找到了一些方法来部分并行化独立像素on the GPU甚至是有趣的CPU-GPU-hybrid approach的计算。

不幸的是,由于CIFilters在可利用的GPU资源方面受到限制(例如,无法访问全局内存),因此Core Image可能不是实现这些技术的最佳框架。您可以直接使用Metal计算着色器(而不是通过Core Image),但这将需要更多的支持代码。

如果您不一定需要进行错误扩散,则仍可以使用有序抖动(可以高度并行化)来获得类似的结果。我还发现了一个nice article。内置的CIDither过滤器也可能使用这种方法。


推荐阅读
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 技嘉秀高端B450主板:不再支持第七代APU,性价比高且兼容锐龙一代和二代
    在台北电脑展上,技嘉展示了一款高端的B450主板,型号为“b450 aorus pro wi-fi”。该主板具有10+1相供电、散热片覆盖的供电区域和芯片组,以及两个m.2插槽和背部IO挡板。虽然不支持第七代APU bristol ridge,但它兼容锐龙一代和二代,且具有较高的性价比。该主板还配备了音频声卡、Wi-Fi无线网卡等功能,是一款性能出色且设计精良的主板。 ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • imnewtotheswiftandxcodeworld,soimhavingaproblemtryingtointegrateapackagetomypro ... [详细]
  • 设计完成后,将所完成的作品交由老师检查。管理进程接收申请进入的信号,在消息队列中取下申请进入队列的用户进程的信息,针对当前临界区状态,写一个回馈信息 ... [详细]
  • LinusTorvalds发布了 Linux4.17-rc1,关闭了合并窗口。Linux4.17的主 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 关于如何快速定义自己的数据集,可以参考我的前一篇文章PyTorch中快速加载自定义数据(入门)_晨曦473的博客-CSDN博客刚开始学习P ... [详细]
  • OCR:用字符识别方法将形状翻译成计算机文字的过程Matlab:商业数学软件;CUDA:CUDA™是一种由NVIDIA推 ... [详细]
author-avatar
史玥Zaira_717
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有