Skip to content

Instantly share code, notes, and snippets.

@theXYZT
Created November 8, 2025 03:32
Show Gist options
  • Select an option

  • Save theXYZT/8687bec8234610c648a47d8330a872af to your computer and use it in GitHub Desktop.

Select an option

Save theXYZT/8687bec8234610c648a47d8330a872af to your computer and use it in GitHub Desktop.
Interactive Bitmap Generator
import scipy
import numpy as np
import imageio.v3 as iio
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
def xdog(img, sigma, k, p):
img1 = scipy.ndimage.gaussian_filter(img, sigma=sigma)
img2 = scipy.ndimage.gaussian_filter(img, sigma=k * sigma)
return (1 + p) * img1 - p * img2
class ImageProcess:
def __init__(self):
self.raw = iio.imread("mEk4aL6TgMgEpE74xSjwkb.jpg")
self.mask = ~iio.imread("mask.png", mode="1")
# self.raw = iio.imread("800wm.jpeg")
# self.mask = None
self.R = 0.30
self.G = 0.59
self.update_image()
self.SIGMA = 1.2
self.K = 1.5
self.P = 10.0
self.EPS = 0.45
self.N_OPEN = 0
self.N_CLOS = 0
@property
def B(self):
return 1 - self.R - self.G
def update_image(self):
x = np.dot(self.raw, [self.R, self.G, self.B]) / 255.0
self.im = np.clip(x, 0, 1)
def process(self):
temp = xdog(self.im, self.SIGMA, self.K, self.P)
if self.mask is not None:
temp = np.where(temp >= self.EPS, True, False) & self.mask
else:
temp = np.where(temp >= self.EPS, True, False)
if self.N_CLOS:
temp = scipy.ndimage.binary_closing(temp, iterations=self.N_CLOS)
if self.N_OPEN:
temp = scipy.ndimage.binary_opening(temp, iterations=self.N_OPEN)
return ~temp
def save_image(self):
rgb = f"({self.R:+.2f},{self.G:+.2f},{self.B:+.2f})"
par = f"({self.SIGMA:.1f},{self.K:.1f},{self.P:.1f},{self.EPS:+.2f})"
par += f"_O{self.N_OPEN}-C{self.N_CLOS}"
filename = f"saved_images/Arecibo_{par}_{rgb}.png"
iio.imwrite(filename, self.process().astype(bool))
print(f"Saved as {filename}")
IMP = ImageProcess()
fig = plt.figure(figsize=(16, 9))
ax_im = fig.add_axes((0, 0.25, 1, 0.75), aspect=1.0)
ax_im.axis("off")
imim = ax_im.imshow(IMP.process(), cmap="gray", vmin=0, vmax=1)
def update_sigma(val):
IMP.SIGMA = val
imim.set_data(IMP.process())
fig.canvas.draw_idle()
def update_k(val):
IMP.K = val
imim.set_data(IMP.process())
fig.canvas.draw_idle()
def update_p(val):
IMP.P = val
imim.set_data(IMP.process())
fig.canvas.draw_idle()
def update_thres(val):
IMP.EPS = val
imim.set_data(IMP.process())
fig.canvas.draw_idle()
def update_open(val):
IMP.N_OPEN = val
imim.set_data(IMP.process())
fig.canvas.draw_idle()
def update_clos(val):
IMP.N_CLOS = val
imim.set_data(IMP.process())
fig.canvas.draw_idle()
def update_R(val):
IMP.R = val
b_slide.set_val(IMP.B)
IMP.update_image()
imim.set_data(IMP.process())
fig.canvas.draw_idle()
def update_G(val):
IMP.G = val
b_slide.set_val(IMP.B)
IMP.update_image()
imim.set_data(IMP.process())
fig.canvas.draw_idle()
def save_image(val):
IMP.save_image()
l, w, h = 0.06, 0.4, 0.05
ax_s = fig.add_axes((l, 0.02, w, h))
ax_k = fig.add_axes((l, 0.07, w, h))
ax_p = fig.add_axes((l, 0.12, w, h))
ax_e = fig.add_axes((l, 0.17, w, h))
l = 0.56
ax_r = fig.add_axes((l, 0.17, w, h))
ax_g = fig.add_axes((l, 0.12, w, h))
ax_b = fig.add_axes((l, 0.07, w, h))
ax_x = fig.add_axes((0.58, 0.02, 0.1, h))
ax_y = fig.add_axes((0.74, 0.02, 0.1, h))
ax_z = fig.add_axes((0.86, 0.02, 0.10, h))
s_slide = Slider(ax=ax_s, label=r"$\sigma$", valmin=0, valmax=5, valinit=IMP.SIGMA, valstep=0.1)
s_slide.on_changed(update_sigma)
k_slide = Slider(ax=ax_k, label=r"$k$", valmin=1, valmax=3, valinit=IMP.K, valstep=0.1)
k_slide.on_changed(update_k)
p_slide = Slider(ax=ax_p, label=r"$p$", valmin=0, valmax=20, valinit=IMP.P, valstep=0.2)
p_slide.on_changed(update_p)
e_slide = Slider(ax=ax_e, label=r"Threshold", valmin=-0.5, valmax=1.5, valinit=IMP.EPS, valstep=0.01)
e_slide.on_changed(update_thres)
r_slide = Slider(ax=ax_r, label="R", valmin=-1, valmax=1, valinit=IMP.R, valstep=0.01)
r_slide.on_changed(update_R)
g_slide = Slider(ax=ax_g, label="G", valmin=-1, valmax=1, valinit=IMP.G, valstep=0.01)
g_slide.on_changed(update_G)
b_slide = Slider(ax=ax_b, label="B", valmin=-1, valmax=2, valinit=IMP.B, valstep=0.01)
x_slide = Slider(ax=ax_x, label="Open ", valmin=0, valmax=9, valstep=1, valinit=IMP.N_OPEN)
x_slide.on_changed(update_open)
y_slide = Slider(ax=ax_y, label="Close ", valmin=0, valmax=9, valstep=1, valinit=IMP.N_OPEN)
y_slide.on_changed(update_clos)
save_bt = Button(ax=ax_z, label="Save Image")
save_bt.on_clicked(save_image)
r_slide.set_val(0.0)
g_slide.set_val(-0.5)
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment