KevinJuanCarlos23's picture
Upload app.py
455dcd8 verified
Raw
History Blame Contribute Delete
45.4 kB
import cv2
import numpy as np
import gradio as gr
from sklearn.cluster import KMeans
from scipy.fftpack import dct, idct
from skimage.morphology import skeletonize
# Grayscale
def to_greyscale(image):
return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Negative
def to_negative(image):
return 255 - image
# Adjust Color
def adjust_color(image, r_factor=1.0, g_factor=1.0, b_factor=1.0):
b, g, r = cv2.split(image)
b = np.clip(b * b_factor, 0, 255).astype(np.uint8)
g = np.clip(g * g_factor, 0, 255).astype(np.uint8)
r = np.clip(r * r_factor, 0, 255).astype(np.uint8)
return cv2.merge([b, g, r])
# Flip
def flip_image(image, direction="horizontal"):
flip_code = {'horizontal': 1, 'vertical': 0, 'diagonal': -1}
return cv2.flip(image, flip_code.get(direction, 1))
# Translate
def translate(image, x_offset, y_offset):
rows, cols = image.shape[:2]
M = np.float32([[1, 0, x_offset],
[0, 1, y_offset]])
return cv2.warpAffine(image, M, (cols, rows))
# Scale
def scale_image(image, width=None, height=None, keep_aspect_ratio=True):
h, w = image.shape[:2]
if keep_aspect_ratio:
if width is not None:
ratio = width / float(w)
height = int(h * ratio)
elif height is not None:
ratio = height / float(h)
width = int(w * ratio)
if width is None:
width = w
if height is None:
height = h
return cv2.resize(image, (width, height), interpolation=cv2.INTER_AREA)
# Rotate
def rotate(image, angle, clockwise=True):
rows, cols = image.shape[:2]
center = (cols / 2, rows / 2)
if clockwise:
angle = -angle
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, M, (cols, rows))
return rotated
# Crop
def crop(image, x, y, w, h):
return image[y:y+h, x:x+w]
# Blend
def blend(image1, image2, alpha=0.5):
if image2 is None:
return image1 # If No Second Image, Just Return First
if image1.shape != image2.shape:
image2 = cv2.resize(image2, (image1.shape[1], image1.shape[0]))
return cv2.addWeighted(image1, alpha, image2, 1 - alpha, 0)
# Brightness & Contrast
def adjust_brightness_contrast(image, brightness=50, contrast=1.2):
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
v = np.clip(v + brightness, 0, 255).astype(np.uint8)
final_hsv = cv2.merge((h, s, v))
image_brightness = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
image_float = image_brightness.astype(np.float32)
image_contrast = np.clip(contrast * (image_float - 128) + 128, 0, 255)
return image_contrast.astype(np.uint8)
# Color Filter
def color_filter(image, lower_bound, upper_bound):
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower_bound, upper_bound)
return cv2.bitwise_and(image, image, mask=mask)
def apply_sepia(image):
image_float = image.astype(np.float32)
sepia_kernel = np.array([
[0.272, 0.534, 0.131],
[0.349, 0.686, 0.168],
[0.393, 0.769, 0.189]
])
sepia_image = image_float @ sepia_kernel.T
sepia_image = np.clip(sepia_image, 0, 255)
return sepia_image.astype(np.uint8)
def apply_cyanotype(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cyan_image = np.zeros_like(image)
cyan_image[:, :, 0] = np.clip(gray / 2, 0, 255) # Blue Channel
cyan_image[:, :, 1] = np.clip(gray, 0, 255) # Green Channel
cyan_image[:, :, 2] = 255 # Red Channel
return cyan_image
# Border
def add_border(image, top, bottom, left, right, color_str="(0,0,0)"):
color = tuple(map(int, color_str.strip("()").split(",")))
return cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)
# Overlay
def overlay(image1, image2, x, y, alpha=0.5):
if image2 is None:
return image1
h1, w1 = image1.shape[:2]
h2, w2 = image2.shape[:2]
if y + h2 > h1 or x + w2 > w1:
# Resize Overlay If It Goes Beyond Boundary
new_h = min(h2, h1 - y)
new_w = min(w2, w1 - x)
image2 = cv2.resize(image2, (new_w, new_h))
h2, w2 = new_h, new_w
roi = image1[y:y+h2, x:x+w2]
blended = cv2.addWeighted(roi, 1 - alpha, image2, alpha, 0)
image1[y:y+h2, x:x+w2] = blended
return image1
def pixelwise_operation(image1, image2, operation, brightness_factor=1.2):
if operation == 'Bitwise (NOT)':
# Only Needs Image1
return cv2.bitwise_not(image1)
# For Other Option, We Need 2 Images
if image2 is None:
return image1
# Resize If Mismatch
if image1.shape != image2.shape:
image2 = cv2.resize(image2, (image1.shape[1], image1.shape[0]))
if operation == 'Add':
return cv2.add(image1, image2)
elif operation == 'Subtract':
return cv2.subtract(image1, image2)
elif operation == 'Multiply':
return cv2.multiply(image1, image2)
elif operation == 'Divide':
epsilon = 1e-5
image2 = image2.astype(np.float32) + epsilon
image1 = image1.astype(np.float32)
divided = cv2.divide(image1, image2)
divided_normalized = cv2.normalize(divided, None, 0, 255, cv2.NORM_MINMAX)
return cv2.convertScaleAbs(divided_normalized, alpha=brightness_factor, beta=0)
elif operation == 'Bitwise (AND)':
return cv2.bitwise_and(image1, image2)
elif operation == 'Bitwise (OR)':
return cv2.bitwise_or(image1, image2)
elif operation == 'Bitwise (XOR)':
return cv2.bitwise_xor(image1, image2)
else:
return image1
# FFT
def fft_image(image: np.ndarray):
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
f = np.fft.fft2(image)
fshift = np.fft.fftshift(f)
magnitude = 20 * np.log(np.abs(fshift) + 1e-8)
return cv2.normalize(magnitude, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
# Mean Blur
def mean_blur(image: np.ndarray, ksize: int = 3):
return cv2.blur(image, (ksize, ksize))
# Gaussian Blur
def gaussian_blur(image: np.ndarray, ksize: int = 3, sigma: float = 1.0):
if ksize % 2 == 0:
ksize += 1
return cv2.GaussianBlur(image, (ksize, ksize), sigma)
# Median Blur
def median_blur(image: np.ndarray, ksize: int = 3):
if ksize % 2 == 0:
ksize += 1
return cv2.medianBlur(image, ksize)
# Sobel Edge
def sobel_edge(image: np.ndarray, ksize: int = 3):
if ksize % 2 == 0:
ksize += 1
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
sobelx = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=ksize)
sobely = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=ksize)
magnitude = cv2.magnitude(sobelx, sobely)
return np.clip(magnitude, 0, 255).astype(np.uint8)
# Canny Edge
def canny_edge(image: np.ndarray, t1: float, t2: float):
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return cv2.Canny(image, t1, t2)
# Laplacian Edge
def laplacian_edge(image: np.ndarray, ksize: int = 3):
if ksize % 2 == 0:
ksize += 1
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
lap = cv2.Laplacian(image, cv2.CV_64F, ksize=ksize)
return np.clip(np.abs(lap), 0, 255).astype(np.uint8)
# Histogram Equalization
def histogram_equalization(image: np.ndarray):
if len(image.shape) == 2:
return cv2.equalizeHist(image)
else:
b, g, r = cv2.split(image)
b_eq = cv2.equalizeHist(b)
g_eq = cv2.equalizeHist(g)
r_eq = cv2.equalizeHist(r)
return cv2.merge([b_eq, g_eq, r_eq])
# Contrast Stretching
def contrast_stretch(image: np.ndarray, in_low: int, in_high: int):
img_float = image.astype(np.float32)
img_stretched = (img_float - in_low) * (255.0 / max(in_high - in_low, 1e-6))
return np.clip(img_stretched, 0, 255).astype(np.uint8)
# Gamma Correction
def gamma_correction(image: np.ndarray, gamma: float = 1.0):
inv_gamma = 1.0 / gamma
table = np.array([(i / 255.0) ** inv_gamma * 255 for i in range(256)]).astype("uint8")
return cv2.LUT(image, table)
# RLE
def rle_encode(image: np.ndarray):
if len(image.shape) > 2:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
flat = image.flatten()
encoding = []
prev = flat[0]
count = 1
for pixel in flat[1:]:
if pixel == prev:
count += 1
else:
encoding.append((int(prev), count))
prev = pixel
count = 1
encoding.append((int(prev), count))
return encoding
def rle_decode(encoding, shape):
flat_image = []
for pixel_value, count in encoding:
flat_image.extend([pixel_value] * count)
return np.array(flat_image, dtype=np.uint8).reshape(shape)
# DCT
def apply_dct(image, threshold_ratio=0.01):
dct_transformed = dct(dct(image.T, norm='ortho').T, norm='ortho')
dct_thresh = dct_transformed * (np.abs(dct_transformed) > threshold_ratio * np.max(dct_transformed))
img_reconstructed = idct(idct(dct_thresh.T, norm='ortho').T, norm='ortho')
return np.clip(img_reconstructed, 0, 255).astype(np.uint8)
# Global Thresholding
def global_threshold(image: np.ndarray, thresh: int = 128):
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(image, thresh, 255, cv2.THRESH_BINARY)
return binary
# Adaptive Thresholding
def adaptive_threshold(image: np.ndarray, block_size: int = 11, C: int = 2):
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY, block_size, C)
# K-Means
def kmeans_segmentation(image: np.ndarray, k: int = 2):
if len(image.shape) == 2:
data = image.reshape((-1, 1))
else:
data = image.reshape((-1, 3))
data = np.float32(data)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
_, labels, centers = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
centers = np.uint8(centers)
segmented = centers[labels.flatten()]
if len(image.shape) == 2:
segmented = segmented.reshape((image.shape[0], image.shape[1]))
else:
segmented = segmented.reshape((image.shape[0], image.shape[1], 3))
return segmented
# Binarize
def binarize_image(image: np.ndarray, thresh: int = 127):
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(image, thresh, 255, cv2.THRESH_BINARY)
return binary
# Morphological
def morphological_op(binary_image: np.ndarray, op_type: str, ksize: int, iterations: int):
kernel = np.ones((ksize, ksize), np.uint8)
if op_type == 'erosion':
return cv2.erode(binary_image, kernel, iterations=iterations)
elif op_type == 'dilation':
return cv2.dilate(binary_image, kernel, iterations=iterations)
elif op_type == 'opening':
return cv2.morphologyEx(binary_image, cv2.MORPH_OPEN, kernel, iterations=iterations)
elif op_type == 'closing':
return cv2.morphologyEx(binary_image, cv2.MORPH_CLOSE, kernel, iterations=iterations)
else:
return binary_image
# Extract Boundary
def extract_boundary(binary_image: np.ndarray, ksize: int = 3):
kernel = np.ones((ksize, ksize), np.uint8)
eroded = cv2.erode(binary_image, kernel, iterations=1)
return cv2.subtract(binary_image, eroded)
# Skeletonize
def skeletonize_image(binary_image: np.ndarray):
from skimage.morphology import skeletonize
if len(binary_image.shape) == 3:
binary_image = cv2.cvtColor(binary_image, cv2.COLOR_BGR2GRAY)
bin_bool = (binary_image > 0)
skeleton = skeletonize(bin_bool)
return (skeleton * 255).astype(np.uint8)
# Add Noise
def add_noise(image: np.ndarray, mean=0, std=25):
gauss = np.random.normal(mean, std, image.shape)
noisy = image.astype(np.float32) + gauss
return np.clip(noisy, 0, 255).astype(np.uint8)
# Wiener Filter
def wiener_filter(image: np.ndarray, ksize=5, noise_var=0.01):
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
kernel = np.ones((ksize, ksize), np.float32) / (ksize * ksize)
local_mean = cv2.filter2D(image, -1, kernel)
local_var = cv2.filter2D(image ** 2, -1, kernel) - (local_mean ** 2)
noise_var = max(noise_var, 0.0001)
result = local_mean + ((local_var - noise_var) / np.maximum(local_var, noise_var)) * (image - local_mean)
return np.clip(result, 0, 255).astype(np.uint8)
# Gaussian Filter
def gaussian_filter_restoration(image: np.ndarray, ksize=5, sigma=1.0):
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return cv2.GaussianBlur(image, (ksize, ksize), sigma)
# Inpainting
def inpaint_image(image: np.ndarray, top_left, bottom_right, inpaint_radius=3):
mask = np.zeros(image.shape[:2], dtype=np.uint8)
r1, c1 = top_left
r2, c2 = bottom_right
mask[r1:r2, c1:c2] = 255
return cv2.inpaint(image, mask, inpaint_radius, cv2.INPAINT_TELEA)
# Feature Detection
def detect_and_compute(image: np.ndarray, method='ORB'):
if len(image.shape) == 3:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
else:
gray = image
if method == 'ORB':
detector = cv2.ORB_create()
else:
try:
detector = cv2.SIFT_create()
except:
detector = cv2.ORB_create()
kp, des = detector.detectAndCompute(gray, None)
return kp, des
# Matching Feature
def match_features(img1: np.ndarray, img2: np.ndarray, method='ORB', match_method='BF'):
kp1, des1 = detect_and_compute(img1, method)
kp2, des2 = detect_and_compute(img2, method)
if des1 is None or des2 is None or len(des1) < 2 or len(des2) < 2:
return img1
if match_method == 'BF':
norm_type = cv2.NORM_HAMMING if method=='ORB' else cv2.NORM_L2
bf = cv2.BFMatcher(norm_type, crossCheck=True)
matches = bf.match(des1, des2)
else:
if method == 'ORB':
index_params = dict(algorithm=6, table_number=6, key_size=12, multi_probe_level=1)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.match(des1, des2)
else:
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
matched_img = cv2.drawMatches(img1, kp1, img2, kp2, matches[:20], None,
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
return matched_img
# Template Matching
def template_match(main_img: np.ndarray, templ: np.ndarray, threshold=0.8):
if len(main_img.shape) == 3:
main_gray = cv2.cvtColor(main_img, cv2.COLOR_BGR2GRAY)
else:
main_gray = main_img
if len(templ.shape) == 3:
templ_gray = cv2.cvtColor(templ, cv2.COLOR_BGR2GRAY)
else:
templ_gray = templ
result = cv2.matchTemplate(main_gray, templ_gray, cv2.TM_CCOEFF_NORMED)
loc = np.where(result >= threshold)
display = main_img.copy()
h, w = templ_gray.shape
for pt in zip(*loc[::-1]):
cv2.rectangle(display, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
return display
# Tab: Basic Operations
def tab_basic_ops(img1, img2, operation, r_factor, g_factor, b_factor, flip_dir,
trans_x, trans_y, scale_w, scale_h, scale_keep_aspect, rot_angle, rot_clockwise,
crop_x, crop_y, crop_w, crop_h, blend_alpha, bright_val, contrast_val, filter_lower_H,
filter_lower_S, filter_lower_V, filter_upper_H, filter_upper_S, filter_upper_V,
border_top, border_bottom, border_left, border_right, border_color_str, overlay_x,
overlay_y, overlay_alpha):
if img1 is None:
return None
try:
color_tuple = tuple(map(int, border_color_str.split(',')))
if len(color_tuple) != 3:
color_tuple = (0, 0, 0)
except:
color_tuple = (0, 0, 0)
if operation == "Greyscale":
return to_greyscale(img1)
elif operation == "Negative":
return to_negative(img1)
elif operation == "Adjust Color":
return adjust_color(img1, r_factor, g_factor, b_factor)
elif operation == "Flip":
return flip_image(img1, flip_dir)
elif operation == "Translate":
return translate(img1, trans_x, trans_y)
elif operation == "Scale":
return scale_image(img1, width=scale_w, height=scale_h, keep_aspect_ratio=scale_keep_aspect)
elif operation == "Rotate":
return rotate(img1, rot_angle, clockwise=rot_clockwise)
elif operation == "Crop":
return crop(img1, crop_x, crop_y, crop_w, crop_h)
elif operation == "Blend":
return blend(img1, img2, alpha=blend_alpha)
elif operation == "Brightness & Contrast":
return adjust_brightness_contrast(img1, bright_val, contrast_val)
elif operation == "Color Filter":
lowerb = (filter_lower_H, filter_lower_S, filter_lower_V)
upperb = (filter_upper_H, filter_upper_S, filter_upper_V)
return color_filter(img1, lowerb, upperb)
elif operation == "Sepia":
return apply_sepia(img1)
elif operation == "Cyanotype":
return apply_cyanotype(img1)
elif operation == "Add Border":
return add_border(img1, border_top, border_bottom, border_left, border_right, color=color_tuple)
elif operation == "Overlay":
return overlay(img1, img2, overlay_x, overlay_y, alpha=overlay_alpha)
else:
return img1
# Mathematical Operations
def tab_pixelwise_op(image1, image2, operation):
if image1 is None:
return None
return pixelwise_operation(image1, image2, operation)
# Transforms & Filtering
def tab_transform_filter(image, operation, ksize=3, sigma=1.0, t1=50, t2=150):
if image is None:
return None
if operation == "FFT":
return fft_image(image)
elif operation == "Mean Blur":
return mean_blur(image, ksize)
elif operation == "Gaussian Blur":
return gaussian_blur(image, ksize, sigma)
elif operation == "Median Blur":
return median_blur(image, ksize)
elif operation == "Sobel Edge":
return sobel_edge(image, ksize)
elif operation == "Canny Edge":
return canny_edge(image, t1, t2)
elif operation == "Laplacian Edge":
return laplacian_edge(image, ksize)
else:
return image
# Image Enhancement
def tab_enhancement(image, operation, in_low=0, in_high=255, gamma_val=1.0):
if image is None:
return None
if operation == "Histogram Equalization":
return histogram_equalization(image)
elif operation == "Contrast Stretching":
return contrast_stretch(image, in_low, in_high)
elif operation == "Gamma Correction":
return gamma_correction(image, gamma_val)
else:
return image
# Image Compression
def tab_compression(image, operation, threshold_ratio=0.005):
if image is None:
return None
if operation == "RLE":
encoded = rle_encode(image)
decoded_image = rle_decode(encoded, image.shape[:2])
return decoded_image
elif operation == "DCT":
compressed_image = apply_dct(image, threshold_ratio=threshold_ratio)
return compressed_image
else:
return image
# Image Segmentation
def tab_segmentation(image, operation, threshold=128, block_size=11, C=2, k=3):
if image is None:
return None
if operation == "Global Thresholding":
return global_threshold(image, threshold)
elif operation == "Adaptive Thresholding":
return adaptive_threshold(image, block_size, C)
elif operation == "K-Means":
return kmeans_segmentation(image, k)
else:
return image
# Binary Processing
def tab_binary(image, operation, thresh=127, morph_op_='erosion', ksize=3, iterations=1):
if image is None:
return None
if operation == "Binarize":
return binarize_image(image, thresh)
elif operation == "Morphological":
bin_img = binarize_image(image, thresh=127) if len(image.shape) == 3 else image
return morphological_op(bin_img, morph_op_, ksize, iterations)
elif operation == "Extract Boundary":
bin_img = binarize_image(image, thresh=127) if len(image.shape) == 3 else image
return extract_boundary(bin_img, ksize=ksize)
elif operation == "Skeletonize":
bin_img = binarize_image(image, thresh=127) if len(image.shape) == 3 else image
return skeletonize_image(bin_img)
else:
return image
# Image Restoration
def tab_restoration(image, operation, ksize=5, sigma=1.0, noise_var=0.01, top_left_r=0, top_left_c=0, bot_right_r=10, bot_right_c=10, inpaint_radius=3):
if image is None:
return None
if operation == "Add Noise + Wiener Filter":
noisy = add_noise(image, 0, 25)
return wiener_filter(noisy, ksize, noise_var)
elif operation == "Add Noise + Gaussian Filter":
noisy = add_noise(image, 0, 25)
return gaussian_filter_restoration(noisy, ksize, sigma)
elif operation == "Inpainting":
return inpaint_image(image, (top_left_r, top_left_c), (bot_right_r, bot_right_c), inpaint_radius)
else:
return image
# Image Matching
def tab_matching(image1, image2, operation, feature_method='ORB', match_method='BF', templ_thresh=0.8):
if image1 is None or image2 is None:
return None
if operation == "Feature Detection & Matching":
return match_features(image1, image2, method=feature_method, match_method=match_method)
elif operation == "Template Matching":
return template_match(image1, image2, threshold=templ_thresh)
else:
return None
def build_demo():
with gr.Blocks() as demo:
gr.Markdown("## Image Processing And Recognition")
with gr.Tabs():
# Basic Image Operations
with gr.TabItem("Basic Image Operations"):
gr.Markdown("### Basic Image Operations")
# Tab Greyscale
with gr.TabItem("Greyscale"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
run_basic = gr.Button("Apply")
run_basic.click(
fn=to_greyscale,
inputs=[input_image_basic1],
outputs=[output_image_basic]
)
# Tab Negative
with gr.TabItem("Negative"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
run_basic = gr.Button("Apply")
run_basic.click(
fn=to_negative,
inputs=[input_image_basic1],
outputs=[output_image_basic]
)
# Tab Adjust Color
with gr.TabItem("Adjust Color"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
r_factor = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="Red Factor")
g_factor = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="Green Factor")
b_factor = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="Blue Factor")
run_basic = gr.Button("Apply")
run_basic.click(
fn=adjust_color,
inputs=[input_image_basic1, r_factor, g_factor, b_factor],
outputs=[output_image_basic]
)
# Tab Flip
with gr.TabItem("Flip"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
flip_dir = gr.Dropdown(["horizontal", "vertical", "diagonal"], value="horizontal", label="Flip Direction")
run_basic = gr.Button("Apply")
run_basic.click(
fn=flip_image,
inputs=[input_image_basic1, flip_dir],
outputs=[output_image_basic]
)
# Tab Translate
with gr.TabItem("Translate"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
trans_x = gr.Slider(-200, 200, value=0, step=1, label="Translate X")
trans_y = gr.Slider(-200, 200, value=0, step=1, label="Translate Y")
run_basic = gr.Button("Apply")
run_basic.click(
fn=translate,
inputs=[input_image_basic1, trans_x, trans_y],
outputs=[output_image_basic]
)
# Tab Scale
with gr.TabItem("Scale"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
scale_w = gr.Number(value=None, label="Scale Width (None=auto)")
scale_h = gr.Number(value=None, label="Scale Height (None=auto)")
scale_keep_aspect = gr.Checkbox(value=True, label="Keep Aspect Ratio")
run_basic = gr.Button("Apply")
run_basic.click(
fn=scale_image,
inputs=[input_image_basic1, scale_w, scale_h, scale_keep_aspect],
outputs=[output_image_basic]
)
# Tab Rotate
with gr.TabItem("Rotate"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
rot_angle = gr.Slider(-180, 180, value=0, step=1, label="Rotate Angle")
rot_clockwise = gr.Checkbox(value=True, label="Rotate Clockwise")
run_basic = gr.Button("Apply")
run_basic.click(
fn=rotate,
inputs=[input_image_basic1, rot_angle, rot_clockwise],
outputs=[output_image_basic]
)
# Tab Crop
with gr.TabItem("Crop"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
crop_x = gr.Slider(0, 300, value=0, step=1, label="Crop X")
crop_y = gr.Slider(0, 300, value=0, step=1, label="Crop Y")
crop_w = gr.Slider(0, 300, value=100, step=1, label="Crop Width")
crop_h = gr.Slider(0, 300, value=100, step=1, label="Crop Height")
run_basic = gr.Button("Apply")
run_basic.click(
fn=crop,
inputs=[input_image_basic1, crop_x, crop_y, crop_w, crop_h],
outputs=[output_image_basic]
)
# Tab Blend
with gr.TabItem("Blend"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
input_image_basic2 = gr.Image(label="Input Image 2 (for blend)")
output_image_basic = gr.Image(label="Output Image")
blend_alpha = gr.Slider(0.0, 1.0, value=0.5, step=0.05, label="Blend Alpha")
run_basic = gr.Button("Apply")
run_basic.click(
fn=blend,
inputs=[input_image_basic1, input_image_basic2, blend_alpha],
outputs=[output_image_basic]
)
# Tab Brightness & Contrast
with gr.TabItem("Brightness & Contrast"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
bright_val = gr.Slider(-100, 100, value=50, step=1, label="Brightness")
contrast_val = gr.Slider(0.1, 3.0, value=1.2, step=0.1, label="Contrast")
run_basic = gr.Button("Apply")
run_basic.click(
fn=adjust_brightness_contrast,
inputs=[input_image_basic1, bright_val, contrast_val],
outputs=[output_image_basic]
)
# Tab Color Filter
with gr.TabItem("Color Filter"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
filter_type = gr.Radio(
["Custom", "Sepia", "Cyanotype"],
label="Select Filter Type",
value="Custom",
)
filter_lower_H = gr.Slider(0, 179, value=0, step=1, label="Filter Lower H")
filter_lower_S = gr.Slider(0, 255, value=0, step=1, label="Filter Lower S")
filter_lower_V = gr.Slider(0, 255, value=0, step=1, label="Filter Lower V")
filter_upper_H = gr.Slider(0, 179, value=179, step=1, label="Filter Upper H")
filter_upper_S = gr.Slider(0, 255, value=255, step=1, label="Filter Upper S")
filter_upper_V = gr.Slider(0, 255, value=255, step=1, label="Filter Upper V")
run_basic = gr.Button("Apply")
def apply_selected_filter(image, filter_type, lower_H, lower_S, lower_V, upper_H, upper_S, upper_V):
if filter_type == "Custom":
lowerb = (lower_H, lower_S, lower_V)
upperb = (upper_H, upper_S, upper_V)
return color_filter(image, lowerb, upperb)
elif filter_type == "Sepia":
return apply_sepia(image)
elif filter_type == "Cyanotype":
return apply_cyanotype(image)
run_basic.click(
fn=apply_selected_filter,
inputs=[input_image_basic1, filter_type, filter_lower_H, filter_lower_S, filter_lower_V, filter_upper_H, filter_upper_S, filter_upper_V],
outputs=[output_image_basic]
)
# Tab Add Border
with gr.TabItem("Add Border"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
output_image_basic = gr.Image(label="Output Image")
border_top = gr.Slider(0, 100, value=0, step=1, label="Border Top")
border_bottom = gr.Slider(0, 100, value=0, step=1, label="Border Bottom")
border_left = gr.Slider(0, 100, value=0, step=1, label="Border Left")
border_right = gr.Slider(0, 100, value=0, step=1, label="Border Right")
border_color_str = gr.Textbox(value="0,0,0", label="Border Color (R,G,B)")
run_basic = gr.Button("Apply")
run_basic.click(
fn=add_border,
inputs=[input_image_basic1, border_top, border_bottom, border_left, border_right, border_color_str],
outputs=[output_image_basic]
)
# Tab Overlay
with gr.TabItem("Overlay"):
with gr.Row():
input_image_basic1 = gr.Image(label="Input Image 1")
input_image_basic2 = gr.Image(label="Input Image 2 (for overlay)")
output_image_basic = gr.Image(label="Output Image")
overlay_x = gr.Slider(0, 300, value=0, step=1, label="Overlay X")
overlay_y = gr.Slider(0, 300, value=0, step=1, label="Overlay Y")
overlay_alpha = gr.Slider(0.0, 1.0, value=0.5, step=0.05, label="Overlay Alpha")
run_basic = gr.Button("Apply")
run_basic.click(
fn=overlay,
inputs=[input_image_basic1, input_image_basic2, overlay_x, overlay_y, overlay_alpha],
outputs=[output_image_basic]
)
# Mathematical Operations
with gr.TabItem("Mathematical Operations"):
gr.Markdown("### Mathematical Operations on Images")
with gr.Row():
input_image_math1 = gr.Image(label="Input Image 1")
input_image_math2 = gr.Image(label="Input Image 2 (ignored if NOT)")
output_image_math = gr.Image(label="Output Image")
operation_math = gr.Radio(
choices=["Add", "Subtract", "Multiply", "Divide",
"Bitwise (AND)", "Bitwise (OR)", "Bitwise (XOR)", "Bitwise (NOT)"],
value="add",
label="Pixelwise Operation"
)
run_math = gr.Button("Apply Operation")
run_math.click(
tab_pixelwise_op,
inputs=[input_image_math1, input_image_math2, operation_math],
outputs=[output_image_math]
)
# Transforms & Filtering
with gr.TabItem("Transforms & Filtering"):
gr.Markdown("### Transforms & Filtering")
with gr.Row():
input_image_tf = gr.Image(type="numpy", label="Input Image") # Ensure 'numpy' type for the input image
output_image_tf = gr.Image(type="numpy", label="Output Image") # Ensure 'numpy' type for the output image
# Dropdown to choose operation
operation_tf = gr.Radio(
choices=["FFT", "Mean Blur", "Gaussian Blur", "Median Blur",
"Sobel Edge", "Canny Edge", "Laplacian Edge"],
value="FFT",
label="Select Operation"
)
# Sliders for kernel size, sigma, and Canny thresholds
ksize_tf = gr.Slider(1, 15, step=1, value=3, label="Kernel Size (blur/edge)")
sigma_tf = gr.Slider(0.1, 5.0, step=0.1, value=1.0, label="Sigma (Gaussian)")
t1_tf = gr.Slider(0, 255, value=50, step=1, label="Canny Threshold1")
t2_tf = gr.Slider(0, 255, value=150, step=1, label="Canny Threshold2")
run_tf = gr.Button("Process")
def _process_tf(img, op, k, s, c1, c2):
return tab_transform_filter(img, op, k, s, c1, c2)
# Set up the button click interaction
run_tf.click(_process_tf,
inputs=[input_image_tf, operation_tf, ksize_tf, sigma_tf, t1_tf, t2_tf],
outputs=[output_image_tf])
# Enhancement
with gr.TabItem("Enhancement"):
gr.Markdown("### Image Enhancement")
with gr.Row():
input_image_en = gr.Image(label="Input Image")
output_image_en = gr.Image(label="Output Image")
operation_en = gr.Radio(
choices=["Histogram Equalization", "Contrast Stretching", "Gamma Correction"],
value="Histogram Equalization",
label="Select Enhancement"
)
in_low_en = gr.Slider(0, 255, value=0, step=1, label="In Low (Contrast Stretch)")
in_high_en = gr.Slider(0, 255, value=255, step=1, label="In High (Contrast Stretch)")
gamma_en = gr.Slider(0.1, 5.0, value=1.0, step=0.1, label="Gamma")
run_en = gr.Button("Enhance")
def _process_en(img, op, low, high, gm):
return tab_enhancement(img, op, low, high, gm)
run_en.click(_process_en,
inputs=[input_image_en, operation_en, in_low_en, in_high_en, gamma_en],
outputs=[output_image_en])
# Compression
with gr.TabItem("Compression"):
gr.Markdown("### Image Compression")
with gr.Row():
input_image_comp = gr.Image(label="Input Image")
output_comp_image = gr.Image(label="Output Image", interactive=False)
operation_comp = gr.Radio(
choices=["RLE", "DCT"],
value="RLE",
label="Select Compression"
)
run_comp = gr.Button("Compress")
def _process_comp(img, op):
result = tab_compression(img, op)
return result
run_comp.click(
_process_comp,
inputs=[input_image_comp, operation_comp],
outputs=[output_comp_image]
)
# Tab: Segmentation
with gr.TabItem("Segmentation"):
gr.Markdown("### Image Segmentation")
with gr.Row():
input_image_seg = gr.Image(label="Input Image")
output_image_seg = gr.Image(label="Output Image")
operation_seg = gr.Radio(
choices=["Global Thresholding", "Adaptive Thresholding", "K-Means"],
value="Global Thresholding",
label="Select Segmentation"
)
thresh_seg = gr.Slider(0, 255, value=128, step=1, label="Threshold (Global)")
block_seg = gr.Slider(3, 31, step=2, value=11, label="Block Size (Adaptive)")
c_seg = gr.Slider(0, 10, value=2, step=1, label="C (Adaptive)")
k_seg = gr.Slider(2, 10, value=3, step=1, label="K (K-Means)")
run_seg = gr.Button("Segment")
def _process_seg(img, op, th, bs, c_, k_):
return tab_segmentation(img, op, th, bs, c_, k_)
run_seg.click(_process_seg,
inputs=[input_image_seg, operation_seg, thresh_seg, block_seg, c_seg, k_seg],
outputs=[output_image_seg])
# Tab: Binary Processing
with gr.TabItem("Binary Processing"):
gr.Markdown("### Binary Image Processing")
with gr.Row():
input_image_bin = gr.Image(label="Input Image")
output_image_bin = gr.Image(label="Output Image")
operation_bin = gr.Radio(
choices=["Binarize", "Morphological", "Extract Boundary", "Skeletonize"],
value="Binarize",
label="Select Operation"
)
thresh_bin = gr.Slider(0, 255, value=127, step=1, label="Threshold")
morph_op_bin = gr.Dropdown(
choices=["erosion", "dilation", "opening", "closing"],
value="erosion",
label="Morphological Operation"
)
ksize_bin = gr.Slider(1, 15, value=3, step=1, label="Kernel Size")
iter_bin = gr.Slider(1, 10, value=1, step=1, label="Iterations")
run_bin = gr.Button("Process Binary")
def _process_bin(img, op, th, mop, ks, iters):
return tab_binary(img, op, th, mop, ks, iters)
run_bin.click(_process_bin,
inputs=[input_image_bin, operation_bin, thresh_bin, morph_op_bin, ksize_bin, iter_bin],
outputs=[output_image_bin])
# Tab: Restoration
with gr.TabItem("Restoration"):
gr.Markdown("### Image Restoration")
with gr.Row():
input_image_rest = gr.Image(label="Input Image")
output_image_rest = gr.Image(label="Output Image")
operation_rest = gr.Radio(
choices=["Add Noise + Wiener Filter", "Add Noise + Gaussian Filter", "Inpainting"],
value="Add Noise + Wiener Filter",
label="Select Restoration"
)
ksize_rest = gr.Slider(1, 15, value=5, step=1, label="Kernel Size (Wiener/Gaussian)")
sigma_rest = gr.Slider(0.1, 5.0, value=1.0, step=0.1, label="Sigma (Gaussian)")
noise_var_rest = gr.Slider(0.001, 1.0, value=0.01, step=0.01, label="Noise Var (Wiener)")
top_left_r = gr.Number(value=0, label="Inpaint Top Row")
top_left_c = gr.Number(value=0, label="Inpaint Left Col")
bot_right_r = gr.Number(value=50, label="Inpaint Bottom Row")
bot_right_c = gr.Number(value=50, label="Inpaint Right Col")
inpaint_rad = gr.Slider(1, 10, value=3, step=1, label="Inpaint Radius")
run_rest = gr.Button("Restore")
def _process_rest(img, op, ks, sg, nv, r1, c1, r2, c2, ipr):
return tab_restoration(img, op, ks, sg, nv, int(r1), int(c1), int(r2), int(c2), ipr)
run_rest.click(_process_rest,
inputs=[input_image_rest, operation_rest, ksize_rest, sigma_rest, noise_var_rest,
top_left_r, top_left_c, bot_right_r, bot_right_c, inpaint_rad],
outputs=[output_image_rest])
# Tab: Matching
with gr.TabItem("Matching"):
gr.Markdown("### Image Matching")
with gr.Row():
input_image_match1 = gr.Image(label="Main Image / Image1")
input_image_match2 = gr.Image(label="Template / Image2")
output_image_match = gr.Image(label="Output Image")
operation_match = gr.Radio(
choices=["Feature Detection & Matching", "Template Matching"],
value="Feature Detection & Matching",
label="Select Matching Operation"
)
feature_method = gr.Dropdown(choices=["ORB", "SIFT"], value="ORB", label="Feature Method")
match_method = gr.Dropdown(choices=["BF", "FLANN"], value="BF", label="Match Method")
templ_thresh = gr.Slider(0.0, 1.0, value=0.8, step=0.01, label="Template Threshold")
run_match = gr.Button("Match")
def _process_match(img1, img2, op, fm, mm, thr):
return tab_matching(img1, img2, op, fm, mm, thr)
run_match.click(_process_match,
inputs=[input_image_match1, input_image_match2, operation_match,
feature_method, match_method, templ_thresh],
outputs=[output_image_match])
return demo
if __name__ == "__main__":
demo = build_demo()
demo.launch(share=True)