首页 > 编程语言 >python taichi 加速 dither仿色抖动算法

python taichi 加速 dither仿色抖动算法

时间:2024-11-16 22:56:50浏览次数:1  
标签:err taichi img python 仿色 shape quant ti def

教程

9种dither算法与历史发展
wiki: bayer有序抖动
python生成任意规模bayer矩阵
知乎:dither启发的艺术效果,半调/柱形
taichi ndarray文档

代码实现

taichi_dither.py
#!/bin/env python
import taichi as ti
import numpy as np
import cv2
from copy import deepcopy
ti.init(arch=ti.cpu)

DEBUG=True
MAX=255
np.set_printoptions(threshold=np.inf, linewidth=180)  # numpy打印选项
img_from='/home/n/photo/Portal_Companion_Cube.jpg'
# img_from='/home/n/photo/neco godness.jpg'
# img_from='/media/n/data/download/firefox/updated/browser/chrome/icons/default/default32.png'

def show_image(img):
    if isinstance(img, str):
        img = cv2.imread(img)
    elif img.dtype != 'uint8':
        img = np.clip(img, 0, MAX)  # 将图片像素值限制在 0~255 之间
        img = img.astype(np.uint8)
    
    # 显示图片
    cv2.imshow('Image', img)
    while True:
        key = cv2.waitKey(1) & 0xFF
        if key == 27:  # 27 是 ESC 键的 ASCII 码
            break
    cv2.destroyAllWindows()


PALETTE=[
0x00,0xFF
]
# img2d=ti.types.ndarray(dtype=ti.math.vec3, ndim=2)
type_img2d = ti.types.ndarray(element_dim=0,ndim=2)
type_bayerM = ti.types.ndarray(element_dim=0,ndim=2)

@ti.func
def clamp(x,min=-MAX,max=MAX):
    """控制出血阈值,建议min in [-256,0]"""
    return ti.math.clamp(x,min,max)
    # return np.clip(x,min,max)

@ti.kernel
def dither_basic(img:type_img2d):
    h,w = img.shape
    for i in range(h):
      for j in range(w):
        min_distance = MAX
        oldpixel = img[i, j]
        newpixel = 0
        for c in ti.static(PALETTE):
            distance = abs(img[i, j] - c)
            if distance < min_distance:
                min_distance = distance
                newpixel = c
        img[i, j] = newpixel
        if j + 1 < w:
            img[i, j+1] += oldpixel - newpixel

@ti.kernel
def dither_floyd(img:type_img2d):
    h,w = img.shape
    for i in range(h):
      for j in range(w):
    # for i,j in ti.ndrange(h,w):  # taichi的ti.ndrange有bug,与下面的结果不同!
        oldpixel = img[i, j]
        newpixel = 0 if oldpixel < 128 else MAX
        img[i, j] = newpixel
        quant_error = oldpixel - newpixel
        if j + 1 < img.shape[1]:
            img[i, j + 1] += quant_error * 7 >> 4
        if i + 1 < img.shape[0]:
            if j - 1 >= 0:
                img[i + 1, j - 1] += quant_error * 3 >> 4
            img[i + 1, j] += quant_error * 5 >> 4

def bit_reverse(x, n):
    return int(bin(x)[2:].zfill(n)[::-1], 2)

def bit_interleave(x, y, n):
    x = bin(x)[2:].zfill(n)
    y = bin(y)[2:].zfill(n)
    return int(''.join(''.join(i) for i in zip(x, y)), 2)

def bayer_entry(x, y, n):
    return bit_reverse(bit_interleave(x ^ y, y, n), 2*n)

def bayer_matrix(n):
    """https://gamedev.stackexchange.com/questions/130696/how-to-generate-bayer-matrix-of-arbitrary-size"""
    r = range(2**n)
    return [[bayer_entry(x, y, n) for x in r] for y in r]

@ti.kernel
def dither_bayer(img:type_img2d, bayerM:type_bayerM):
    h,w = img.shape
    n = bayerM.shape[0]
    for i in range(h):
      for j in range(w):
        threshold = bayerM[i % n, j % n] * MAX // (n**2)
        if img[i, j] > threshold:
            img[i, j] = MAX
        else:
            img[i, j] = 0

@ti.kernel
def dither_atkinson(img:type_img2d):
    h,w = img.shape
    for i in range(h):
      for j in range(w):
        oldpixel = img[i, j]
        newpixel = 0 if oldpixel < 128 else MAX
        img[i, j] = newpixel
        quant_err = oldpixel - newpixel

        if j + 1 < img.shape[1]:
            img[i, j + 1] += quant_err >> 3
        if j + 2 < img.shape[1]:
            img[i, j + 2] += quant_err >> 3
        if i + 1 < img.shape[0]:
            if j - 1 >= 0:
                img[i + 1, j - 1] += quant_err >> 3
            img[i + 1, j] += quant_err >> 3
            if j + 1 < img.shape[1]:
                img[i + 1, j + 1] += quant_err >> 3
            if j + 2 < img.shape[1]:
                img[i + 1, j + 2] += quant_err >> 3
        if i + 2 < img.shape[0]:
            if j - 1 >= 0:
                img[i + 2, j - 1] += quant_err >> 3
            img[i + 2, j] += quant_err >> 3
            if j + 1 < img.shape[1]:
                img[i + 2, j + 1] += quant_err >> 3
            if j + 2 < img.shape[1]:
                img[i + 2, j + 2] += quant_err >> 3

def diff(img1,img2):
    return np.sum(np.abs(img1-img2))

img = cv2.imread(img_from)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_u8 = deepcopy(img) if DEBUG else None
img = img.astype(np.int32)  # 转换为 int32 类型

if DEBUG:
    cmd = 'diff(img,img_u8)'
    print('i32<-u8',cmd,'=', eval(cmd))

    # print('Raw:')
    # print(img, '\n')

n=4
bayerM = ti.ndarray(shape=(2**n, 2**n), dtype=ti.u8)
bayerM.from_numpy(np.matrix(bayer_matrix(n), dtype=np.uint8))
dither_bayer(img, bayerM)
if DEBUG:
    img_i32 = deepcopy(img)

    # print('dithered:',diff(img,img_u8),np.max(img), np.min(img), img.shape)
    # print(img, '\n')

if DEBUG:
    img = np.clip(img, 0, MAX)
    img = img.astype(np.uint8)
    cmd = 'diff(img,img_i32)'
    print('u8<-i32',cmd,'=', eval(cmd),np.max(img), np.min(img))

    # print(img, '\n')
show_image(img)



# neighbors = [(-1, -1), (-1, ), (-1, +1),
#              (0, -1),             (0, +1),
#              (+1, -1), (+1, ), (+1, +1)] # 简化写法

# values = [1, 2, 3, 4, 5, 6, 7, 8]  # 示例值
# # a = np.arange(100).reshape(10, 10)
# a = np.zeros((10, 10))
# print(a,'\n')
# for i in range(10-3):
#   for j in range(10-3):
#     for (x, y), value in zip(neighbors, values):
#         a[i+x, j+y] = value
# print(a,'\n')

标签:err,taichi,img,python,仿色,shape,quant,ti,def
From: https://www.cnblogs.com/nolca/p/18550084

相关文章

  • Python--scikit-learn
    数据集sklearn.datasetsfromsklearn.datasetsimportload_iris,fetch_20newsgroups小数据集下载load_xxx大数据集下载fetch_xxx模型KNNK-近邻算法参考距离计算k值选择kd树fromsklearn.neighborsimportKNeighborsClassifierfromsklearn.neighborsimpor......
  • 使用python语言实现获取当前时间,按照电子表样式打印到控制台
    使用python语言实现获取当前时间,按照电子表样式打印到控制台clock.py1fromdatetimeimportdatetime23#数字04zero_line_01='---'5zero_line_02='||'6zero_line_03='||'7zero_line_04='||'8zer......
  • 【动手做】Python实现线性回归
    线性回归是机器学习中形式比较简单的模型,能够很好的进行推导和求解,也便于图形化展示。关于线性回归的概念和表示,在线性回归的概念与表示有比较详细的的介绍。本文通过手动实现、调用scikit-learn类库两种方式演示了线性回归模型,并通过matplotlib进行了可视化展示。实现过程本......
  • python实现十进制转换二进制,tkinter界面
    目录需求效果代码实现代码解释需求python实现十进制转换二进制效果代码实现importtkinterastkfromtkinterimportmessageboxdefconvert_to_binary():try:#获取输入框中的十进制数decimal_number=int(entry.get())#转......
  • Python 语法基础:赋值、深浅拷贝、可变与不可变对象
    Python是一种广泛使用的高级编程语言,其语法简洁且功能强大。本文将详细讲解Python中的赋值、深浅拷贝以及可变与不可变对象的基本概念和使用方法。一、赋值赋值是编程中最基本的操作之一,它用于将值或对象绑定到变量名。在Python中,赋值使用等号=来进行。a=10......
  • python文件排序都有哪些方法
    在python环境中提供两种排序方案:用库函数sorted()对字符串排序,它的对象是字符;用函数sort()对数字排序,它的对象是数字,如果读取文件的话,需要进行处理(把文件后缀名‘屏蔽’)。(1)首先:我测试的文件夹是/img/,里面的文件都是图片,如下图所示:(2)测试库函数sorted(),直接贴出代码:impor......
  • 使用Python实现智能食品安全监测的深度学习模型
    食品安全是关乎公共健康的重要议题。随着科技的发展,深度学习技术在食品安全监测中的应用越来越广泛,通过自动化和智能化手段,可以有效提高食品质量检测的效率和准确性。本文将介绍如何使用Python实现一个智能食品安全监测的深度学习模型,并通过代码示例展示实现过程。项目概述......
  • Python基础:探索迭代器(Iterator)的奥秘
    引言在当今的科技时代,Python作为一种功能强大且广泛应用的编程语言,在数据处理、人工智能、网络爬虫等诸多领域发挥着不可替代的作用。迭代器作为Python中的一个重要概念,对于高效处理数据、优化算法等有着极大的意义。它能够以一种简洁而有效的方式遍历数据结构,无论是大型数......
  • 【Python】基础语法速览(上)
    本文力图用最快的方式向大家陈列Python的基础语法,适合接触过其他编程语言后快速上手Python或供查阅巩固用参考书籍:《Python程序设计人工智能案例实践》[美]保罗·戴特尔哈维·戴特尔著码字不易,求点赞收藏加关注有问题欢迎评论区讨论目录Python基础语法速览(上)变......
  • Python实现Graham Scan算法并进行凸包计算
    目录使用GrahamScan算法进行凸包计算第一部分:GrahamScan算法概述1.1什么是GrahamScan算法?1.2算法的应用场景1.3算法的优点和局限第二部分:算法的数学基础与步骤2.1凸包的定义与性质2.2算法的关键步骤2.3极角计算公式2.4算法流程图第三部分......