-
Notifications
You must be signed in to change notification settings - Fork 3
/
chapter-7.py
228 lines (201 loc) · 9 KB
/
chapter-7.py
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
import sys
import cv2
import numpy as np
# Draw vertical seam on top of the image
def overlay_vertical_seam(img, seam):
img_seam_overlay = np.copy(img)
# Extract the list of points from the seam
x_coords, y_coords = np.transpose([(i,int(j)) for i,j in enumerate(seam)])
# Draw a green line on the image using the list of points
img_seam_overlay[x_coords, y_coords] = (0,255,0)
return img_seam_overlay
# Compute the energy matrix from the input image
def compute_energy_matrix(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Compute X derivative of the image
sobel_x = cv2.Sobel(gray,cv2.CV_64F,1,0,ksize=3)
# Compute Y derivative of the image
sobel_y = cv2.Sobel(gray,cv2.CV_64F,0,1,ksize=3)
abs_sobel_x = cv2.convertScaleAbs(sobel_x)
abs_sobel_y = cv2.convertScaleAbs(sobel_y)
# Return weighted summation of the two images i.e. 0.5*X + 0.5*Y
return cv2.addWeighted(abs_sobel_x, 0.5, abs_sobel_y, 0.5, 0)
# Find vertical seam in the input image
def find_vertical_seam(img, energy):
rows, cols = img.shape[:2]
# Initialize the seam vector with 0 for each element
seam = np.zeros(img.shape[0])
# Initialize distance and edge matrices
dist_to = np.zeros(img.shape[:2]) + float("inf")
dist_to[0,:] = np.zeros(img.shape[1])
edge_to = np.zeros(img.shape[:2])
# Dynamic programming; iterate using double loop and compute the paths efficiently
for row in range(rows-1):
for col in range(cols):
if col != 0:
if dist_to[row+1, col-1] > dist_to[row, col] + energy[row+1, col-1]:
dist_to[row+1, col-1] = dist_to[row, col] +energy[row+1, col-1]
edge_to[row+1, col-1] = 1
if dist_to[row+1, col] > dist_to[row, col] + energy[row+1,col]:
dist_to[row+1, col] = dist_to[row, col] + energy[row+1,col]
edge_to[row+1, col] = 0
if col != cols-1:
if dist_to[row+1, col+1] > dist_to[row, col] +energy[row+1, col+1]:
dist_to[row+1, col+1] = dist_to[row, col] +energy[row+1, col+1]
edge_to[row+1, col+1] = -1
# Retracing the path
seam[rows-1] = np.argmin(dist_to[rows-1, :])
for i in (x for x in reversed(range(rows)) if x > 0):
seam[i-1] = seam[i] + edge_to[i, int(seam[i])]
return seam
# Remove the input vertical seam from the image
def remove_vertical_seam(img, seam):
rows, cols = img.shape[:2]
# To delete a point, move every point after it one step towards the left
for row in range(rows):
for col in range(int(seam[row]), cols-1):
img[row, col] = img[row, col+1]
# Discard the last column to create the final output image
img = img[:, 0:cols-1]
return img
'''
if __name__=='__main__':
# Make sure the size of the input image is reasonable.
# Large images take a lot of time to be processed.
# Recommended size is 640x480.
img_input = cv2.imread(sys.argv[1])
# Use a small number to get started. Once you get an
# idea of the processing time, you can use a bigger number.
# To get started, you can set it to 20.
num_seams = int(sys.argv[2])
img = np.copy(img_input)
img_overlay_seam = np.copy(img_input)
energy = compute_energy_matrix(img)
for i in range(num_seams):
seam = find_vertical_seam(img, energy)
img_overlay_seam = overlay_vertical_seam(img_overlay_seam, seam)
img = remove_vertical_seam(img, seam)
energy = compute_energy_matrix(img)
print('Number of seams removed =', i+1)
cv2.imshow('Input', img_input)
cv2.imshow('Seams', img_overlay_seam)
cv2.imshow('Output', img)
cv2.waitKey()
'''
#Can we expand an image?
# Add a vertical seam to the image
def add_vertical_seam(img, seam, num_iter):
seam = seam + num_iter
rows, cols = img.shape[:2]
zero_col_mat = np.zeros((rows,1,3), dtype=np.uint8)
img_extended = np.hstack((img, zero_col_mat))
for row in range(rows):
for col in range(cols, int(seam[row]), -1):
img_extended[row, col] = img[row, col-1]
# To insert a value between two columns, take the average value of the neighbors. It looks smooth this way and we can avoid unwanted artifacts.
for i in range(3):
v1 = img_extended[row, int(seam[row])-1, i]
v2 = img_extended[row, int(seam[row])+1, i]
img_extended[row, int(seam[row]), i] = (int(v1)+int(v2))/2
return img_extended
'''
if __name__=='__main__':
img_input = cv2.imread(sys.argv[1])
num_seams = int(sys.argv[2])
img = np.copy(img_input)
img_output = np.copy(img_input)
img_overlay_seam = np.copy(img_input)
energy = compute_energy_matrix(img)
for i in range(num_seams):
seam = find_vertical_seam(img, energy)
img_overlay_seam = overlay_vertical_seam(img_overlay_seam, seam)
img = remove_vertical_seam(img, seam)
img_output = add_vertical_seam(img_output, seam, i)
energy = compute_energy_matrix(img)
print('Number of seams added =', i+1)
cv2.imshow('Input', img_input)
cv2.imshow('Seams', img_overlay_seam)
cv2.imshow('Output', img_output)
cv2.waitKey()
'''
#####################################
# #
#Can we remove an object completely ######
#####################################
# Draw rectangle on top of the input image
def draw_rectangle(event, x, y, flags, params):
global x_init, y_init, drawing, top_left_pt, bottom_right_pt, img_orig
# Detecting a mouse click
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
x_init, y_init = x, y
# Detecting mouse movement
elif event == cv2.EVENT_MOUSEMOVE:
if drawing:
top_left_pt, bottom_right_pt = (x_init,y_init), (x,y)
img[y_init:y, x_init:x] = 255 - img_orig[y_init:y, x_init:x]
cv2.rectangle(img, top_left_pt, bottom_right_pt, (0,255,0), 2)
# Detecting the mouse button up event
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
top_left_pt, bottom_right_pt = (x_init,y_init), (x,y)
# Create the "negative" film effect for the selected # region
img[y_init:y, x_init:x] = 255 - img[y_init:y, x_init:x]
# Draw rectangle around the selected region
cv2.rectangle(img, top_left_pt, bottom_right_pt, (0,255,0), 2)
rect_final = (x_init, y_init, x-x_init, y-y_init)
# Remove the object in the selected region
remove_object(img_orig, rect_final)
# Computing the energy matrix using modified algorithm
def compute_energy_matrix_modified(img, rect_roi):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Compute the X derivative
sobel_x = cv2.Sobel(gray,cv2.CV_64F,1,0,ksize=3)
# Compute the Y derivative
sobel_y = cv2.Sobel(gray,cv2.CV_64F,0,1,ksize=3)
abs_sobel_x = cv2.convertScaleAbs(sobel_x)
abs_sobel_y = cv2.convertScaleAbs(sobel_y)
# Compute weighted summation i.e. 0.5*X + 0.5*Y
energy_matrix = cv2.addWeighted(abs_sobel_x, 0.5, abs_sobel_y, 0.5, 0)
x,y,w,h = rect_roi
# We want the seams to pass through this region, so make sure the energy values in this region are set to 0
energy_matrix[y:y+h, x:x+w] = 0
return energy_matrix
# Remove the object from the input region of interest
def remove_object(img, rect_roi):
num_seams = rect_roi[2] + 10
energy = compute_energy_matrix_modified(img, rect_roi)
# Start a loop and remove one seam at a time
for i in range(num_seams):
# Find the vertical seam that can be removed
seam = find_vertical_seam(img, energy)
# Remove that vertical seam
img = remove_vertical_seam(img, seam)
x,y,w,h = rect_roi
# Compute energy matrix after removing the seam
energy = compute_energy_matrix_modified(img, (x,y,w-i,h))
print('Number of seams removed =', i+1)
img_output = np.copy(img)
# Fill up the region with surrounding values so that the size of the image remains unchanged
for i in range(num_seams):
seam = find_vertical_seam(img, energy)
img = remove_vertical_seam(img, seam)
img_output = add_vertical_seam(img_output, seam, i)
energy = compute_energy_matrix(img)
print('Number of seams added =', i+1)
cv2.imshow('Input', img_input)
cv2.imshow('Output', img_output)
cv2.waitKey()
if __name__=='__main__':
img_input = cv2.imread(sys.argv[1])
drawing = False
img = np.copy(img_input)
img_orig = np.copy(img_input)
cv2.namedWindow('Input')
cv2.setMouseCallback('Input', draw_rectangle)
while True:
cv2.imshow('Input', img)
c = cv2.waitKey(10)
if c == 27:break
#cv2.imwrite('C:/Users/HP/Downloads/opencv-computer_vision/images/flask-crud-removed.jpg', img)
cv2.destroyAllWindows()