0% found this document useful (0 votes)
9 views5 pages

Seam

This Python code implements seam carving to resize images. It takes an input image, calculates energy maps using forward energy, finds minimum seams through backtracking, and removes or inserts seams to shrink or enlarge the image. The code can process multiple images within a directory, applying seam carving and optionally resizing images before outputting results to another directory.

Uploaded by

amars12345
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views5 pages

Seam

This Python code implements seam carving to resize images. It takes an input image, calculates energy maps using forward energy, finds minimum seams through backtracking, and removes or inserts seams to shrink or enlarge the image. The code can process multiple images within a directory, applying seam carving and optionally resizing images before outputting results to another directory.

Uploaded by

amars12345
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 5

import numpy as np

import cv2
import argparse
from scipy import ndimage as ndi
import os

seam_col = np.array([255, 200, 200])


resize = True
RESIZE_W = 500
ENERGY_CON = 100000.0
THRES_CON = 10
FWD_ENERGY = True

def visualize(im, boolmask=None, rotate=False):


vis = im.astype(np.uint8)
if boolmask is not None:
vis[np.where(boolmask == False)] = seam_col
if rotate:
vis = rot_img(vis, False)
cv2.imshow("visualization", vis)
cv2.waitKey(1)
return vis

def resize(image, width):


dim = None
h, w = image.shape[:2]
dim = (width, int(h * width / float(w)))
return cv2.resize(image, dim)

def rot_img(image, cw):


k = 1 if cw else 3
return np.rot90(image, k)

def fwd_energy(im):
h, w = im.shape[:2]
im = cv2.cvtColor(im.astype(np.uint8), cv2.COLOR_BGR2GRAY).astype(np.float64)
energy_fn = np.zeros((h, w))
m = np.zeros((h, w))
U = np.roll(im, 1, axis=0)
L = np.roll(im, 1, axis=1)
R = np.roll(im, -1, axis=1)
cU = np.abs(R - L)
cL = np.abs(U - L) + cU
cR = np.abs(U - R) + cU
for i in range(1, h):
mU = m[i-1]
mL = np.roll(mU, 1)
mR = np.roll(mU, -1)
mULR = np.array([mU, mL, mR])
cULR = np.array([cU[i], cL[i], cR[i]])
mULR += cULR
argmins = np.argmin(mULR, axis=0)
m[i] = np.choose(argmins, mULR)
energy_fn[i] = np.choose(argmins, cULR)
return energy_fn

def add_seam(im, seam_idx):


h, w = im.shape[:2]
out = np.zeros((h, w + 1, 3))
for row in range(h):
col = seam_idx[row]
for ch in range(3):
if col == 0:
p = np.average(im[row, col: col + 2, ch])
out[row, col, ch] = im[row, col, ch]
out[row, col + 1, ch] = p
out[row, col + 1:, ch] = im[row, col:, ch]
else:
p = np.average(im[row, col - 1: col + 1, ch])
out[row, : col, ch] = im[row, : col, ch]
out[row, col, ch] = p
out[row, col + 1:, ch] = im[row, col:, ch]
return out

def remove_seam(im, boolmask):


h, w = im.shape[:2]
boolmask3c = np.stack([boolmask] * 3, axis=2)
return im[boolmask3c].reshape((h, w - 1, 3))

def get_min_seam(im, mask=None, remove_mask=None):


h, w = im.shape[:2]
energy_fn = fwd_energy
M = energy_fn(im)
if mask is not None:
M[np.where(mask > THRES_CON)] = ENERGY_CON
if remove_mask is not None:
M[np.where(remove_mask > THRES_CON)] = -ENERGY_CON * 100
backtrack = np.zeros_like(M, dtype=int)
for i in range(1, h):
for j in range(0, w):
if j == 0:
idx = np.argmin(M[i - 1, j:j + 2])
backtrack[i, j] = idx + j
min_energy = M[i-1, idx + j]
else:
idx = np.argmin(M[i - 1, j - 1:j + 2])
backtrack[i, j] = idx + j - 1
min_energy = M[i - 1, idx + j - 1]
M[i, j] += min_energy
seam_idx = []
boolmask = np.ones((h, w), dtype=bool)
j = np.argmin(M[-1])
for i in range(h-1, -1, -1):
boolmask[i, j] = False
seam_idx.append(j)
j = backtrack[i, j]
seam_idx.reverse()
return np.array(seam_idx), boolmask

def seams_removal(im, num_remove, mask=None, vis=False, rot=False):


for _ in range(num_remove):
seam_idx, boolmask = get_min_seam(im, mask)
if vis:
visualize(im, boolmask, rotate=rot)
im = remove_seam(im, boolmask)
return im, mask

def seams_insertion(im, num_add, mask=None, vis=False, rot=False):


seams_record = []
temp_im = im.copy()
temp_mask = mask.copy() if mask is not None else None
for _ in range(num_add):
seam_idx, boolmask = get_min_seam(temp_im, temp_mask)
if vis:
visualize(temp_im, boolmask, rotate=rot)
seams_record.append(seam_idx)
temp_im = remove_seam(temp_im, boolmask)
seams_record.reverse()
for _ in range(num_add):
seam = seams_record.pop()
im = add_seam(im, seam)
if vis:
visualize(im, rotate=rot)
for rem_seam in seams_record:
rem_seam [np.where(rem_seam >= seam)] += 2
return im, mask

def seam_carve(im, dy, dx, mask=None, vis=False):


im = im.astype(np.float64)
h, w = im.shape[:2]
assert h + dy > 0 and w + dx > 0 and dy <= h and dx <= w
if mask is not None:
mask = mask.astype(np.float64)
out = im
if dx < 0:
out, mask = seams_removal(out, -dx, mask, vis)
elif dx > 0:
out, mask = seams_insertion(out, dx, mask, vis)
if dy < 0:
out = rot_img(out, True)
if mask is not None:
mask = rot_img(mask, True)
out, mask = seams_removal(out, -dy, mask, vis, rot=True)
out = rot_img(out, False)
elif dy > 0:
out = rot_img(out, True)
if mask is not None:
mask = rot_img(mask, True)
out, mask = seams_insertion(out, dy, mask, vis, rot=True)
out = rot_img(out, False)
return out

def process_images_in_directory(input_directory, output_directory, mask_directory=None,


rmask_directory=None):
image_files = [f for f in os.listdir(input_directory) if os.path.isfile(os.path.join(input_directory, f))]
for image_file in image_files:
input_path = os.path.join(input_directory, image_file)
mask_path = os.path.join(mask_directory, image_file) if mask_directory else None
rmask_path = os.path.join(rmask_directory, image_file) if rmask_directory else None
output_name = os.path.join(output_directory, image_file)
im = cv2.imread(input_path)
assert im is not None
mask = cv2.imread(mask_path, 0) if mask_path else None
rmask = cv2.imread(rmask_path, 0) if rmask_path else None
h, w = im.shape[:2]
if resize and w > RESIZE_W:
im = resize(im, width=RESIZE_W)
if mask is not None:
mask = resize(mask, width=RESIZE_W)
if rmask is not None:
rmask = resize(rmask, width=RESIZE_W)
dy = int(0.25 * h)
dx = int(0.25 * w)
output = seam_carve(im, dy, dx, mask, args.get("visualization", False))
cv2.imwrite(output_name, output)

if __name__ == '__main__':
ap = argparse.ArgumentParser()
group = ap.add_mutually_exclusive_group(required=True)
group.add_argument("-resize", action='store_true')
ap.add_argument("-im", required=True)
ap.add_argument("-out" , required=True)
ap.add_argument("-dy", type=int, default=0)
ap.add_argument("-dx", type=int, default=0)
ap.add_argument("-visualization", action='store_true')
args = vars(ap.parse_args())
input_directory = os.path.abspath(args["im"])
output_directory = os.path.abspath(args["out"])
process_images_in_directory(input_directory, output_directory)

You might also like