Chapter 5
5.1 Image Pixels and Colors
5.1.1 Picture display
fig() + image(img_gray, cmap='gray')
5.1.2 Image data structure analysis
print(type(img_gray))
print(img_gray.shape)
printMat2D(img_gray)
5.1.3 Pixel - single pixel readout
val = img_gray[18, 16]
print(val)
5.1.4 Pixel - single pixel modification
img_gray_copy = image_copy(img_gray)
img_gray_copy[18, 16] = 255
fig() + image(img_gray_copy, cmap='gray')
5.1.5 Pixel-line modification
img_gray_copy = image_copy(img_gray)
img_gray_copy[18:25, 16] = 255
fig() + image(img_gray_copy, cmap='gray')
5.1.6 Pixel-area modification
img_gray_copy = image_copy(img_gray)
img_gray_copy[18:25, 16:25] = 255
fig() + image(img_gray_copy, cmap='gray')
5.1.7 Pixel-area modification shorthand
img_gray_copy = image_copy(img_gray)
img_gray_copy[8:25, 8:25] = 255
fig() + image(img_gray_copy, cmap='gray')
5.1.8 Exercise - Flower Border
img_gray_copy = image_copy(img_gray)
img_gray_copy[3:23, 22] = 255
img_gray_copy[2:23, 7] = 255
img_gray_copy[23, 7:23] = 255
img_gray_copy[2, 8:23] = 255
fig() + image(img_gray_copy, cmap='gray')
5.1.9 Color pictures
fig() + image(img_shibe)
print(img_shibe.shape)
5.1.10 Color Channel Splitting
red, green, blue = color_split(img_shibe)
fig(1, 3) + [image(red, cmap='Reds'), image(green, cmap='Greens'), image(blue, cmap='Blues')]
merged_img = color_merge(red, green, blue)
fig() + image(merged_img)
5.1.11 Color Channel Splitting - Another Approach
r = img_shibe[:, :, 0]
g = img_shibe[:, :, 1]
b = img_shibe[:, :, 2]
fig(1, 3) + [image(r, cmap='Reds'), image(g, cmap='Greens'), image(b, cmap='Blues')]
5.2 Image color transformation
5.2.1 Color transformation warm-up 1 - channel swap
fig() + image(img_raw)
img_bgr = image_copy(img_raw)
tmp = image_copy(img_bgr[:, :, 0])
img_bgr[:, :, 0] = img_bgr[:, :, 2]
img_bgr[:, :, 2] = tmp
fig() + image(img_bgr)
5.2.2 Color transformation warm-up 2 - warm color system
img_warm = image_copy(img_raw)
img_warm = image_int2float(img_warm)
img_warm[:, :, 2] = img_warm[:, :, 2] / 2
img_warm = image_float2int(img_warm)
fig() + image(img_warm)
5.2.3 Matrix Form - Channel Swap
mat = [
[0, 0, 1],
[0, 1, 0],
[1, 0, 0]
]
img_bgr = image_copy(img_raw)
img_bgr = map_color_space(img_bgr, mat)
fig() + image(img_bgr)
5.2.4 Exercise - Realize Warm Color System in Matrix Form
mat = [[0, 0, 1],
[0, 1, 0],
[1, 0, 0]]
img_bgr = image_copy(img_raw)
img_bar_warm = image_int2float(img_bgr)
img_bar_warm[:, :, 2] /= 2
img_bar_warm = image_float2int(img_bar_warm)
fig() + image(img_bar_warm)
5.2.5 Matrix Form - Vintage Effect
mat = [
[0.393, 0.769, 0.189],
[0.349, 0.686, 0.168],
[0.272, 0.534, 0.131]
]
img_retro = image_copy(img_raw)
img_retro = image_int2float(img_retro)
img_retro = map_color_space(img_retro, mat)
img_retro = bound(img_retro, 0, 255)
img_retro = image_float2int(img_retro)
fig() + image(img_retro)
5.2.6 Matrix Form - Red-Green Blindness Simulation
rgb2lms_mat = [
[17.8824, 43.5161, 4.11935],
[3.45565, 27.1554, 3.86714],
[0.0299566, 0.184309, 1.46709]
]
lms2rgb_mat = [
[8.09444479e-02, -1.30504409e-01, 1.16721066e-01],
[-1.02485335e-02, 5.40193266e-02, -1.13614708e-01],
[-3.65296938e-04, -4.12161469e-03, 6.93511405e-01]
]
lms_mix_mat = [
[0, 2.02344, -2.52581],
[0, 1, 0],
[0, 0, 1]
]
img_cb = image_copy(img_raw)
img_cb = image_int2float(img_cb)
img_cb = map_color_space(img_cb, rgb2lms_mat)
img_cb = map_color_space(img_cb, lms_mix_mat)
img_cb = map_color_space(img_cb, lms2rgb_mat)
img_cb = bound(img_cb, 0, 255)
img_cb = image_float2int(img_cb)
fig() + image(img_raw)
fig() + image(img_cb)
5.2.7 Exercise - Design your own transformation
import itertools
import random
mat = [
[],
[],
[]
]
for item, _ in itertools.product(mat, range(3)):
item.append(random.random())
img_retro = image_copy(img_raw)
img_retro = image_int2float(img_retro)
img_retro = map_color_space(img_retro, mat)
img_retro = bound(img_retro, 0, 255)
img_retro = image_float2int(img_retro)
fig() + image(img_retro)
5.2.8 From linear transformation to nonlinear transformation - wood carving effect
img_woodcut = image_copy(img_wzj)
img_woodcut = rgb2gray(img_woodcut)
img_woodcut = binary_threshold(img_woodcut, 170, 0, 255)
fig() + image(img_woodcut, cmap='gray')
5.3 Production of image special effects
5.3.1 Frosted glass effects
def groundglass_code(img, k=3):
res = image_copy(img)
H, W = get_image_size(img)
for i in range(H):
for j in range(W):
offset_i = random_int(-k, k)
offset_j = random_int(-k, k)
src_i = i + offset_i
src_j = j + offset_j
src_i = bound(src_i, 0, H - 1)
src_j = bound(src_j, 0, W - 1)
res[i, j, :] = img[src_i, src_j, :]
return res
img_groundglass = groundglass(img_sand,3)
fig() + image(img_sand)
fig() + image(img_groundglass)
5.3.2 Frosted glass expansion - adjust parameters
img_groundglass_ex = groundglass(img_sand,8)
fig() + image(img_sand)
fig() + image(img_groundglass_ex)
5.3.3 Oil painting effects
def oil_painting_code(img, num_bin=2, region_size =4):
H, W = get_image_size(img)
res = image_copy(img)
bin_assignment = compute_bin_assignment(img, num_bin)
for i in range(0, H):
for j in range(0, W):
bb = get_bounding_box(i, j, region_size, H, W)
y1, y2, x1, x2 = bb
img_region = img[y1:y2, x1:x2, :]
bin_assignment_region = bin_assignment[y1:y2, x1:x2]
region_r, region_g, region_b = get_most_frequent_color(img_region, bin_assignment_region)
res[y1:y2, x1:x2, 0] = region_r
res[y1:y2, x1:x2, 1] = region_g
res[y1:y2, x1:x2, 2] = region_b
return res
img_painting = oil_painting(img_sand,3,4)
fig() + image(img_sand)
fig() + image(img_painting)
5.3.4 Oil painting effect extension - adjust parameters
img_painting = oil_painting(img_sand,20,4)
fig() + image(img_sand)
fig() + image(img_painting)
5.4 Image Distortion
5.4.1 Mapping function formula:
Recall the mapping function formula for image warping:
u , v = T ( x , y ) u,v = T(x, y)u,v=T(x,y)
T() corresponds the (x, y) of the original image to the (u, v) pixel of the new image. However, when implemented by a computer, this process is reversed: for a pixel on the new image, we hope to find its corresponding source point on the original image. Therefore, when writing a program, the mapping function formula should actually be written as:
x , y = T − 1 ( u , v ) x, y = T^{-1}(u, v) x,y=T−1(u,v)
5.4.2 Global Warp 1 - Collapse Mapping Function
Collapse mapping function:
x ′ = x ∗ ( 1 − p ∗ r ) / ( 1 − p ) x' = x * (1 - p * r) / (1 - p)x′=x∗(1−p∗r)/(1−p)
y ′ = y ∗ ( 1 − p ∗ r ) / ( 1 − p ) y' = y * (1 - p * r) / (1 - p) y′=y∗(1−p∗r)/(1−p)
r = x 2 + y 2 r = \sqrt{x^2 + y^2} r=x2+y2
def warp1(x, y):
p = 0.4
r = (x**2 + y**2)**0.5
xp = x * (1 - p*r) / (1 - p)
yp = y * (1 - p*r) / (1 - p)
return xp, yp
img_anchor_warp = global_len_warp(img_anchor, warp1)
fig() + image(img_anchor)
fig() + image(img_anchor_warp)
5.4.3 Global Warp 1 - Collapse Warp Effect
def warp1(x, y):
p = 0.4
r = (x**2 + y**2)**0.5
xp = x * (1 - p*r) / (1 - p)
yp = y * (1 - p*r) / (1 - p)
return xp, yp
img_warp_boy = global_len_warp(img_boy, warp1)
fig() + image(img_boy)
fig() + image(img_warp_boy)
5.4.4 Global Distortion 1 - Collapse Exercise
def warp1_ex(x, y):
p = 0.2
r = (x**2 + y**2)**0.5
xp = x * (1 - p*r) / (1 - p)
yp = y * (1 - p*r) / (1 - p)
return xp, yp
img_warp_boy_ex = global_len_warp(img_boy, warp1_ex)
fig() + image(img_boy)
fig() + image(img_warp_boy_ex)
5.4.5 Global Warp 2 - Prism Warp Function
Prism warp function:
x ′ = sin ( x ) ∗ x 2 x' = sin(x) * x^2x′=sin(x)∗x2
y ′ = sin ( y ) ∗ y 2 y' = sin(y) * y^2y′=without ( and ) _∗y2
def warp2(x, y):
xp = sin(x) * x**2
yp = sin(y) * y**2
return xp, yp
img_warp_anchor_ex2 = global_len_warp(img_anchor, warp2)
fig() + image(img_warp_anchor_ex2)
5.4.6 Global Distortion 2 - Prism Distortion Effect
def warp2(x, y):
xp = sin(x) * x**2
yp = sin(y) * y**2
return xp, yp
img_warp_boy2 = global_len_warp(img_boy, warp2)
fig() + image(img_warp_boy2)
5.4.7 Global Warp - Crazy Mode
def warp_ex(x, y):
xp = sin(x) * x
yp = sin(y) * y
return xp, yp
img_warp_boy_insane = global_len_warp(img_boy, warp_ex)
fig() + image(img_warp_boy_insane)
5.4.8 Local Twist - Stretch Twist Function
warp_params = [(125, 125), (0, 80), 120]
img_warp_local_anchor = local_warp_image(img_anchor, warp_params)
warp_params = [(125, 125), (0, 80), 60]
img_warp_local_anchor2 = local_warp_image(img_anchor, warp_params)
fig() + image(img_warp_local_anchor)
fig() + image(img_warp_local_anchor2)
5.4.9 Local Distortion - Stretch Distortion Effect
warp_params = [(100, 100), (0, 20), 50]
img_warp_local_boy = local_warp_image(img_boy, warp_params)
fig() + image(img_warp_local_boy)
5.5 Face key point detection
5.5.1 Face key points
In a series of studies on faces, scientists found that the positioning of some important position coordinates of the face is very important for subsequent tasks, such as face alignment, segmentation, etc. These points are called face key points. Going up in precision, there are 68, 104, and 240 points. The following figure shows the distribution of 68 points:
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-SI8gmBw5-1667613871201)(https://gitee.com/liuyun492/frontiers_in_-computer_-science/raw/img /Typora/%E4%B8%8B%E8%BD%BD.png)]
5.5.2 Face key point detection
points = detect_keypoints(img_boy)
print(points)
5.5.3 Visualization of facial key points
img_boy_with_points = draw_points(img_boy, points)
fig() + image(img_boy_with_points)
5.5.4 Application of Key Points in the Coming Year - find out the positions of the corners of the mouth and the center of the eyebrows
mouth_left = points[48]
mouth_right = points[54]
left_eyebrow = points[19]
right_eyebrow = points[24]
cust_points = [mouth_left, mouth_right, left_eyebrow, right_eyebrow]
img_boy_cust = draw_points(img_boy, cust_points)
fig() + image(img_boy_cust)
5.5.5 Exercise - outline the eyes and mouth
left_eye = points[36:42]
right_eye = points[42:48]
mouth = points[48:60]
img_boy_face = draw_points(img_boy, left_eye + right_eye + mouth)
fig() + image(img_boy_face)
5.5.6 Exercise - Calculating the Center of the Mouth Using Key Points
mouth_up = points[51]
mouth_down = points[57]
mouth_center_y = int((mouth_up[0] + mouth_down[0] + mouth_left[0] + mouth_right[0]) / 4)
mouth_center_x = int((mouth_up[1] + mouth_down[1] + mouth_left[1] + mouth_right[1]) / 4)
mouth_center = (mouth_center_y, mouth_center_x)
img_boy_mouth = draw_points(img_boy, mouth_center)
fig() + image(img_boy_mouth)
5.6 Making dynamic emoticons
5.6.1. Detect keypoints
points = detect_keypoints(img_wzj)
img_with_points = draw_points(img_wzj, points)
fig() + image(img_with_points)
5.6.2 Visual expression control points
mouth_left = points[48]
mouth_right = points[54]
left_eyebrow = points[19]
right_eyebrow = points[24]
cust_points = [mouth_left, mouth_right, left_eyebrow, right_eyebrow]
img_with_points = draw_points(img_wzj, cust_points)
fig() + image(img_with_points)
5.6.3. Set the stretching function and make emoticons
warp_params = [
[left_eyebrow, (0, -5), 35],
[right_eyebrow, (0, -5), 35],
[mouth_left, (-5, -5), 40],
[mouth_right, (5, -5), 40]
]
sticker = make_sticker(img_wzj, warp_params)
fig() + gif(sticker)
5.6.4 Upload pictures and make your own emoticons
You can do this yourself, in fact, you don’t have to write it, just a url of a network map will do.
url = "https://xxxxx"
img_url = imread(url)