Spaces:
Runtime error
Runtime error
File size: 10,908 Bytes
2bb6827 f40fc3d 2bb6827 dffefa4 7688b35 dffefa4 a9e774e 9be9790 dffefa4 dbfbff5 7688b35 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
import numpy as np
import cv2
def assert_image_format(image, fcn_name: str, arg_name: str, force_alpha: bool = True):
if not isinstance(image, np.ndarray):
err_msg = 'The blend_modes function "{fcn_name}" received a value of type "{var_type}" for its argument ' \
'"{arg_name}". The function however expects a value of type "np.ndarray" for this argument. Please ' \
'supply a variable of type np.ndarray to the "{arg_name}" argument.' \
.format(fcn_name=fcn_name, arg_name=arg_name, var_type=str(type(image).__name__))
raise TypeError(err_msg)
if not image.dtype.kind == 'f':
err_msg = 'The blend_modes function "{fcn_name}" received a numpy array of dtype (data type) kind ' \
'"{var_kind}" for its argument "{arg_name}". The function however expects a numpy array of the ' \
'data type kind "f" (floating-point) for this argument. Please supply a numpy array with the data ' \
'type kind "f" (floating-point) to the "{arg_name}" argument.' \
.format(fcn_name=fcn_name, arg_name=arg_name, var_kind=str(image.dtype.kind))
raise TypeError(err_msg)
if not len(image.shape) == 3:
err_msg = 'The blend_modes function "{fcn_name}" received a {n_dim}-dimensional numpy array for its argument ' \
'"{arg_name}". The function however expects a 3-dimensional array for this argument in the shape ' \
'(height x width x R/G/B/A layers). Please supply a 3-dimensional numpy array with that shape to ' \
'the "{arg_name}" argument.' \
.format(fcn_name=fcn_name, arg_name=arg_name, n_dim=str(len(image.shape)))
raise TypeError(err_msg)
if force_alpha and not image.shape[2] == 4:
err_msg = 'The blend_modes function "{fcn_name}" received a numpy array with {n_layers} layers for its ' \
'argument "{arg_name}". The function however expects a 4-layer array representing red, green, ' \
'blue, and alpha channel for this argument. Please supply a numpy array that includes all 4 layers ' \
'to the "{arg_name}" argument.' \
.format(fcn_name=fcn_name, arg_name=arg_name, n_layers=str(image.shape[2]))
raise TypeError(err_msg)
def assert_opacity(opacity, fcn_name: str, arg_name: str = 'opacity'):
if not isinstance(opacity, float) and not isinstance(opacity, int):
err_msg = 'The blend_modes function "{fcn_name}" received a variable of type "{var_type}" for its argument ' \
'"{arg_name}". The function however expects the value passed to "{arg_name}" to be of type ' \
'"float". Please pass a variable of type "float" to the "{arg_name}" argument of function ' \
'"{fcn_name}".' \
.format(fcn_name=fcn_name, arg_name=arg_name, var_type=str(type(opacity).__name__))
raise TypeError(err_msg)
if not 0.0 <= opacity <= 1.0:
err_msg = 'The blend_modes function "{fcn_name}" received the value "{val}" for its argument "{arg_name}". ' \
'The function however expects that the value for "{arg_name}" is inside the range 0.0 <= x <= 1.0. ' \
'Please pass a variable in that range to the "{arg_name}" argument of function "{fcn_name}".' \
.format(fcn_name=fcn_name, arg_name=arg_name, val=str(opacity))
raise ValueError(err_msg)
def _compose_alpha(img_in, img_layer, opacity):
comp_alpha = np.minimum(img_in[:, :, 3], img_layer[:, :, 3]) * opacity
new_alpha = img_in[:, :, 3] + (1.0 - img_in[:, :, 3]) * comp_alpha
np.seterr(divide='ignore', invalid='ignore')
ratio = comp_alpha / new_alpha
ratio[ratio == np.nan] = 0.0
return ratio
def create_hard_light_layover(img_in, img_layer, opacity, disable_type_checks: bool = False):
if not disable_type_checks:
_fcn_name = 'hard_light'
assert_image_format(img_in, _fcn_name, 'img_in')
assert_image_format(img_layer, _fcn_name, 'img_layer')
assert_opacity(opacity, _fcn_name)
img_in_norm = img_in / 255.0
img_layer_norm = img_layer / 255.0
ratio = _compose_alpha(img_in_norm, img_layer_norm, opacity)
comp = np.greater(img_layer_norm[:, :, :3], 0.5) \
* np.minimum(1.0 - ((1.0 - img_in_norm[:, :, :3])
* (1.0 - (img_layer_norm[:, :, :3] - 0.5) * 2.0)), 1.0) \
+ np.logical_not(np.greater(img_layer_norm[:, :, :3], 0.5)) \
* np.minimum(img_in_norm[:, :, :3] * (img_layer_norm[:, :, :3] * 2.0), 1.0)
ratio_rs = np.reshape(np.repeat(ratio, 3), [comp.shape[0], comp.shape[1], comp.shape[2]])
img_out = comp * ratio_rs + img_in_norm[:, :, :3] * (1.0 - ratio_rs)
img_out = np.nan_to_num(np.dstack((img_out, img_in_norm[:, :, 3]))) # add alpha channel and replace nans
return img_out * 255.0
def create_soft_light_layover(img_in, img_layer, opacity, disable_type_checks: bool = False):
if not disable_type_checks:
_fcn_name = 'soft_light'
assert_image_format(img_in, _fcn_name, 'img_in')
assert_image_format(img_layer, _fcn_name, 'img_layer')
assert_opacity(opacity, _fcn_name)
img_in_norm = img_in / 255.0
img_layer_norm = img_layer / 255.0
ratio = _compose_alpha(img_in_norm, img_layer_norm, opacity)
# The following code does this:
# multiply = img_in_norm[:, :, :3]*img_layer[:, :, :3]
# screen = 1.0 - (1.0-img_in_norm[:, :, :3])*(1.0-img_layer[:, :, :3])
# comp = (1.0 - img_in_norm[:, :, :3]) * multiply + img_in_norm[:, :, :3] * screen
# ratio_rs = np.reshape(np.repeat(ratio,3),comp.shape)
# img_out = comp*ratio_rs + img_in_norm[:, :, :3] * (1.0-ratio_rs)
comp = (1.0 - img_in_norm[:, :, :3]) * img_in_norm[:, :, :3] * img_layer_norm[:, :, :3] \
+ img_in_norm[:, :, :3] * (1.0 - (1.0 - img_in_norm[:, :, :3]) * (1.0 - img_layer_norm[:, :, :3]))
ratio_rs = np.reshape(np.repeat(ratio, 3), [comp.shape[0], comp.shape[1], comp.shape[2]])
img_out = comp * ratio_rs + img_in_norm[:, :, :3] * (1.0 - ratio_rs)
img_out = np.nan_to_num(np.dstack((img_out, img_in_norm[:, :, 3]))) # add alpha channel and replace nans
return img_out * 255.0
def stitch_images(image1, image2, overlap_width):
"""Stitch two images side by side with overlapping edges."""
height = min(image1.shape[0], image2.shape[0])
image1 = cv2.resize(image1, (image1.shape[1], height))
image2 = cv2.resize(image2, (image2.shape[1], height))
mask = np.zeros((height, overlap_width), dtype=np.float32)
mask[:, :overlap_width] = np.linspace(1, 0, overlap_width)
mask = np.dstack([mask] * 3)
overlap1 = image1[:, -overlap_width:]
overlap2 = image2[:, :overlap_width]
blended_overlap = overlap1 * mask + overlap2 * (1 - mask)
blended_overlap = blended_overlap.astype(np.uint8)
stitched_image = np.hstack((image1[:, :-overlap_width], blended_overlap, image2[:, overlap_width:]))
return stitched_image
def tile_image_to_dimensions(image, target_width, target_height, overlap_width):
times_width = target_width // (image.shape[1] - overlap_width) + 1
times_height = target_height // (image.shape[0] - overlap_width) + 1
row_image = image
for _ in range(times_width - 1):
row_image = stitch_images(row_image, image, overlap_width)
final_image = row_image
for _ in range(times_height - 1):
final_image = np.vstack((final_image, row_image))
final_image = final_image[:target_height, :target_width]
return final_image
def create_image_with_feather_tile(tile_image, width, height, overlap_width):
from PIL import Image
tile_image = Image.open(tile_image)
tile_image.save("tiled_image_pil_converted.png")
tile_cv2 = cv2.imread("tiled_image_pil_converted.png")
tiled_image = tile_image_to_dimensions(tile_cv2, width, height, overlap_width)
cv2.imwrite('tiled_image.png', tiled_image)
def stitch_images_with_control(image1, image2, overlap_width, direction='horizontal'):
"""Stitch two images side by side or top and bottom with overlapping edges."""
if direction == 'horizontal':
height = min(image1.shape[0], image2.shape[0])
image1 = cv2.resize(image1, (image1.shape[1], height))
image2 = cv2.resize(image2, (image2.shape[1], height))
mask = np.zeros((height, overlap_width), dtype=np.float32)
mask[:, :overlap_width] = np.linspace(1, 0, overlap_width)
mask = np.dstack([mask] * 3)
overlap1 = image1[:, -overlap_width:]
overlap2 = image2[:, :overlap_width]
blended_overlap = overlap1 * mask + overlap2 * (1 - mask)
blended_overlap = blended_overlap.astype(np.uint8)
stitched_image = np.hstack((image1[:, :-overlap_width], blended_overlap, image2[:, overlap_width:]))
elif direction == 'vertical':
width = min(image1.shape[1], image2.shape[1])
image1 = cv2.resize(image1, (width, image1.shape[0]))
image2 = cv2.resize(image2, (width, image2.shape[0]))
mask = np.zeros((overlap_width, width), dtype=np.float32)
mask[:overlap_width, :] = np.linspace(1, 0, overlap_width).reshape(-1, 1)
mask = np.dstack([mask] * 3)
overlap1 = image1[-overlap_width:, :]
overlap2 = image2[:overlap_width, :]
blended_overlap = overlap1 * mask + overlap2 * (1 - mask)
blended_overlap = blended_overlap.astype(np.uint8)
stitched_image = np.vstack((image1[:-overlap_width, :], blended_overlap, image2[overlap_width:, :]))
else:
raise ValueError("Direction must be 'horizontal' or 'vertical'")
return stitched_image
def color_extract(image_path, new_width, new_height):
from PIL import Image
format_image = Image.open(image_path)
format_image.save("pil_image.png")
image = cv2.imread("pil_image.png")
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
height, width, _ = image_rgb.shape
center_pixel = image_rgb[height // 2, width // 2]
color = center_pixel
new_image = np.full((new_height, new_width, 3), color, dtype=np.uint8)
output_path = 'color_image.jpg'
cv2.imwrite(output_path, cv2.cvtColor(new_image, cv2.COLOR_RGB2BGR))
print(f'Color image saved at {output_path}')
def control_texture(texture_image, direction, overlap, width, height):
import os
import cv2
color_extract(texture_image, width, height)
create_image_with_feather_tile(texture_image, width, height, overlap)
img1 = cv2.imread('color_image.jpg')
img2 = cv2.imread('tiled_image.png')
control_tile_image = stitch_images_with_control(img1,
img2, overlap, direction)
os.remove('tiled_image.png')
cv2.imwrite('tiled_image_2.png', control_tile_image)
|