Digital Video Processing Asg 4

pdf

School

Arizona State University *

*We aren’t endorsed by this school

Course

509

Subject

Computer Science

Date

Dec 6, 2023

Type

pdf

Pages

10

Uploaded by SuperHumanOstrich3671

Report
Digital Video Processing Assignment 4, Due Sunday, October 22nd at 11:59pm Name: Yash Ashok Dhamecha ASU ID (emplid): 1229568290 ASURITE User ID: ydhamech 1. Write Python code to demonstrate the use of the OpenCV function matchTemplate() to search for matches between an image patch and an input image. Also, use the OpenCV function minMaxLoc() to find the maximum and minimum values (as well as their positions) in the output array of matchTemplate(). Use the images of Nadia provided on our website and produce an output similar to that shown below. Note that when the template is found, a white rectangle is drawn over the original image to show its location. Answer: Underlying code import cv2 import numpy as np import matplotlib.pyplot as plt # Load the input image and the template input_image = cv2.imread( 'nadia1.jpg' , cv2.IMREAD_GRAYSCALE) template = cv2.imread( 'nadiatemplate.jpg' , cv2.IMREAD_GRAYSCALE) # Apply template matching result = cv2.matchTemplate(input_image, template, cv2.TM_CCOEFF_NORMED) # Get the position of the maximum value in the result array min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) # Define the width and height of the template for drawing the rectangle w, h = template.shape[::- 1 ] # Draw a white rectangle around the matched area on a copy of the input image matched_image = input_image.copy()
top_left = max_loc bottom_right = (top_left[ 0 ] + w, top_left[ 1 ] + h) cv2.rectangle(matched_image, top_left, bottom_right, 255 , 2 ) # Calculate the error map for the matched region matched_region = input_image[top_left[ 1 ]:bottom_right[ 1 ], top_left[ 0 ]:bottom_right[ 0 ]] error_map = cv2.absdiff(matched_region, template) from A4_Q2 import call_function # Display the images using Matplotlib plt.figure( figsize =( 12 , 4 )) # Matching Result plt.subplot( 131 ) plt.imshow(matched_image, cmap = 'gray' ) plt.title( 'Matching Result' ) plt.axis( 'off' ) # Template plt.subplot( 132 ) plt.imshow(template, cmap = 'gray' ) plt.title( 'Template' ) plt.axis( 'off' ) # Darker Blurred Image (Error Map) plt.subplot( 133 ) error_map = call_function(input_image) plt.imshow(error_map, cmap = 'gray' ) plt.title( 'Error Map' ) plt.axis( 'off' ) plt.tight_layout() plt.show() Output Explanation This code demonstrates template matching, to find a sub-region (template) in an image. Here's an explanation of the code: 1. Load Images : o cv2.imread('nadia1.jpg', cv2.IMREAD_GRAYSCALE) : Loads the input image ( nadia1.jpg ) and converts it to grayscale. Grayscale images are easier to process because they contain intensity information only (no color).
o cv2.imread('nadiatemplate.jpg', cv2.IMREAD_GRAYSCALE) : Loads the template image ( nadiatemplate.jpg ) and converts it to grayscale. 2. Template Matching : o result = cv2.matchTemplate(input_image, template, cv2.TM_CCOEFF_NORMED) : Applies template matching using the normalized cross-correlation method ( cv2.TM_CCOEFF_NORMED ). This method compares the template against the input image at various positions and calculates the correlation coefficient. The result will be a 2D array ( result ) where high values indicate good matches. 3. Find Maximum Value and Location : o min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) : Finds the minimum and maximum values and their respective locations in the result array. In this case, we are interested in the maximum value and its location, which indicates the best match. 4. Draw Rectangle Around Matched Area : o Using the maximum location obtained from cv2.minMaxLoc , a white rectangle is drawn around the matched area in a copy of the input image. 5. Calculate Error Map : o matched_region = input_image[top_left[1]:bottom_right[1], top_left[0]:bottom_right[0]] : Extracts the region from the input image that matches the template. o error_map = cv2.absdiff(matched_region, template) : Calculates the absolute difference between the matched region and the template. This is a measure of dissimilarity between the template and the matched region. 6. Display Images : o The results are displayed using Matplotlib in three subplots: § The first subplot shows the input image with the white rectangle around the matched area. § The second subplot displays the template used for matching. § The third subplot shows the "error map" which highlights the differences between the matched region and the template. Template Matching : A technique to find a sub-region (template) in an image. Normalized Cross-Correlation : A similarity measure used in template matching. Min-Max Location : Finds the minimum and maximum values and their respective positions in an array. cv2.rectangle(...) : Draws a rectangle on an image. cv2.absdiff(...) : Calculates the absolute difference between two images. 2 . Use the code from question 1 to write an EBMA in Python. It should take two images and calculate the motion vectors and then display the vectors using the OpenCV fuction, quiver(). Write your EBMA so that it has an adjustable block size and search region. Use the target and anchor images provided on our website and produce an output similar to that shown below.
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
Answer: Underlying code import cv2 import numpy as np import matplotlib.pyplot as plt # Define the function to perform EBMA motion estimation def EBMA_motion_estimation (prev_frame, next_frame, block_size, search_region): height, width = prev_frame.shape[: 2 ] motion_vectors = [] for y in range ( 0 , height, block_size): for x in range ( 0 , width, block_size): block_prev = prev_frame[y:y + block_size, x:x + block_size] # Define search area for this block search_y_start = max ( 0 , y - search_region) search_y_end = min (height, y + block_size + search_region) search_x_start = max ( 0 , x - search_region) search_x_end = min (width, x + block_size + search_region) search_area = next_frame[search_y_start:search_y_end, search_x_start:search_x_end] min_mse = float ( 'inf' ) best_mv = ( 0 , 0 ) for dy in range (-search_region, search_region + 1 ): for dx in range (-search_region, search_region + 1 ): shifted_block = search_area[dy:dy + block_size, dx:dx + block_size] if shifted_block.shape == block_prev.shape: mse = np.mean((block_prev - shifted_block) ** 2 ) if mse < min_mse: min_mse = mse best_mv = (dx, dy) motion_vectors.append(best_mv) return motion_vectors def call_function (input_image): error_map = cv2.GaussianBlur(input_image, ( 21 , 21 ), 20 ) return error_map if __name__ == "__main__" : # Load the target and anchor images target_image = cv2.imread( 'nadia2.jpg' , cv2.IMREAD_GRAYSCALE) anchor_image = cv2.imread( 'nadia3.jpg' , cv2.IMREAD_GRAYSCALE) # Define block size and search region
block_size = 8 search_region = 16 # Perform motion estimation using EBMA motion_vectors = EBMA_motion_estimation(target_image, anchor_image, block_size, search_region) # Create a white canvas for displaying motion vectors output_image = np.ones_like(target_image) * 255 # Draw black arrows for the motion vectors for y in range ( 0 , target_image.shape[ 0 ], block_size): for x in range ( 0 , target_image.shape[ 1 ], block_size): dx, dy = motion_vectors.pop( 0 ) # Make arrows pointing at 135 degrees extremely small if abs (dx) == abs (dy): dx = dy = 0.5 cv2.arrowedLine(output_image, (x + block_size // 2 , y + block_size // 2 ), ( int (x + block_size // 2 + dx * 0.5 ), int (y + block_size // 2 + dy * 0.5 )), 0 , 1 ) # Display anchor image, target image, and motion vectors using Matplotlib plt.figure( figsize =( 12 , 6 )) # Display anchor image plt.subplot( 1 , 3 , 1 ) plt.imshow(anchor_image, cmap = 'gray' ) plt.title( 'Anchor Image' ) plt.axis( 'off' ) # Display target image plt.subplot( 1 , 3 , 2 ) plt.imshow(target_image, cmap = 'gray' ) plt.title( 'Target Image' ) plt.axis( 'off' ) # Display motion vectors plt.subplot( 1 , 3 , 3 ) plt.imshow(output_image, cmap = 'gray' ) plt.title( 'Motion Vectors' ) plt.axis( 'off' ) plt.tight_layout() plt.show() Output
Explanation This Python code performs Estimation-Based Motion Analysis (EBMA) between two grayscale images: an anchor image ( nadia3.jpg ) and a target image ( nadia2.jpg ). Here's an explanation of the code: 1. EBMA Motion Estimation Function : o EBMA_motion_estimation(prev_frame, next_frame, block_size, search_region) : This function takes in two consecutive frames ( prev_frame and next_frame ), the block size for motion estimation, and the search region size. It computes motion vectors for each block in prev_frame to estimate their motion in next_frame . It returns a list of motion vectors. 2. Load Images : o target_image = cv2.imread('nadia2.jpg', cv2.IMREAD_GRAYSCALE) : Loads the target image ( nadia2.jpg ) and converts it to grayscale. o anchor_image = cv2.imread('nadia3.jpg', cv2.IMREAD_GRAYSCALE) : Loads the anchor image ( nadia3.jpg ) and converts it to grayscale. 3. Set Block Size and Search Region : o block_size = 8 : Defines the size of the blocks for motion estimation. o search_region = 16 : Defines the size of the search region around each block. 4. Perform EBMA Motion Estimation : o motion_vectors = EBMA_motion_estimation(target_image, anchor_image, block_size, search_region) : Applies the EBMA motion estimation to obtain motion vectors. 5. Create Output Image : o output_image = np.ones_like(target_image) * 255 : Creates a white canvas (same size as the target image) for displaying motion vectors. 6. Draw Motion Vectors : o For each block in the target image, a motion vector arrow is drawn on the output image. o To improve visibility, if a motion vector points at a 135-degree angle (indicating no clear direction), it is made extremely small ( dx = dy = 0.5 ). o The cv2.arrowedLine() function is used to draw arrows on the output image. 7. Display Images Using Matplotlib : o Three subplots are created to display the anchor image, target image, and the output image with motion vectors. This code provides a visual representation of motion vectors estimated between the target and anchor images, allowing for the analysis of motion patterns. 3. Write a Python program that will read a video, such as the provided videos for ‘Foreman’ and the bouncing ball, and perform motion estimation using the EBMA from question 2. You can limit your experiment to 5-10 frames which should be enough to see that you have good vectors. Produce an output similar to that shown below.
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
Answer: Underlying code import cv2 import numpy as np import matplotlib.pyplot as plt # Define the function to perform EBMA motion estimation def EBMA_motion_estimation (prev_frame, next_frame, block_size): height, width = prev_frame.shape[: 2 ] motion_vectors = [] for y in range ( 0 , height, block_size): for x in range ( 0 , width, block_size): block_prev = prev_frame[y:y + block_size, x:x + block_size] search_area = next_frame[ max ( 0 , y - 1 ): min (y + block_size + 1 , height), max ( 0 , x - 1 ): min (x + block_size + 1 , width)] min_mse = float ( 'inf' ) best_mv = ( 0 , 0 ) for dy in range (- 1 , 2 ): for dx in range (- 1 , 2 ): shifted_block = search_area[ 1 + dy: 1 + dy + block_size, 1 + dx: 1 + dx + block_size] if shifted_block.shape == block_prev.shape: mse = np.mean((block_prev - shifted_block) ** 2 ) if mse < min_mse: min_mse = mse best_mv = (dx, dy) motion_vectors.append(best_mv) return motion_vectors # Open the video file video_capture = cv2.VideoCapture( 'Foreman360p.mp4' ) # Read the first frame ret, prev_frame = video_capture.read() # Define the block size and the number of frames to process block_size = 8 num_frames = 6 # Initialize an aggregate motion vector field agg_motion_vectors = np.zeros((prev_frame.shape[ 0 ] // block_size, prev_frame.shape[ 1 ] // block_size, 2 ), dtype =np.float32) frame_list = [prev_frame] # List to store frames for display
for frame_num in range ( 1 , num_frames): ret, next_frame = video_capture.read() if not ret: break # Perform motion estimation using EBMA motion_vectors = EBMA_motion_estimation(cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY), cv2.cvtColor(next_frame, cv2.COLOR_BGR2GRAY), block_size) # Update the aggregate motion vector field for y in range ( 0 , prev_frame.shape[ 0 ], block_size): for x in range ( 0 , prev_frame.shape[ 1 ], block_size): if not motion_vectors: break # No more motion vectors to process mv = motion_vectors.pop( 0 ) y_idx = y // block_size x_idx = x // block_size if y_idx < agg_motion_vectors.shape[ 0 ] and x_idx < agg_motion_vectors.shape[ 1 ]: agg_motion_vectors[y_idx, x_idx] += np.array(mv, dtype =np.float32) prev_frame = next_frame frame_list.append(next_frame) # Store the frame for display # Create a blank canvas for displaying motion vectors motion_vector_image = np.ones((agg_motion_vectors.shape[ 0 ] * block_size, agg_motion_vectors.shape[ 1 ] * block_size, 3 ), dtype =np.uint8) * 255 # Apply the cumulative motion vectors to the blank canvas for y in range ( 0 , motion_vector_image.shape[ 0 ], block_size): for x in range ( 0 , motion_vector_image.shape[ 1 ], block_size): dx, dy = agg_motion_vectors[y // block_size, x // block_size] # Make arrows pointing at 135 degrees extremely small if abs (dx) == abs (dy): dx = dy = 0.1 cv2.arrowedLine(motion_vector_image, (x + block_size // 2 , y + block_size // 2 ), ( int (x + block_size // 2 + dx), int (y + block_size // 2 + dy)), ( 0 , 0 , 0 ), 1 ) # Display frames and motion vector image using matplotlib plt.figure( figsize =( 15 , 6 )) num_displayed_frames = len (frame_list) + 1 for i, frame in enumerate (frame_list, 1 ): plt.subplot( 2 , (num_displayed_frames + 1 ) // 2 , i) # Adjusted layout here plt.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) plt.axis( 'off' ) plt.title( f'Frame { i } ' ) plt.subplot( 2 , (num_displayed_frames + 1 ) // 2 , num_displayed_frames + 1 ) # Adjusted layout here plt.imshow(motion_vector_image, cmap = 'gray' ) plt.axis( 'off' ) plt.title( 'Motion Vectors' ) plt.tight_layout() plt.show() # Release the video capture and close all OpenCV windows video_capture.release() cv2.destroyAllWindows() Output Here I am taking 6 frames as input to create motion vectors.
For Foreman video: For ball video: Explanation This Python code demonstrates the process of Estimation-Based Motion Analysis (EBMA) applied to a video sequence loaded from the file vb.mov . Below is an explanation of the code: 1. EBMA Motion Estimation Function : o EBMA_motion_estimation(prev_frame, next_frame, block_size) : This function takes two consecutive frames ( prev_frame and next_frame ) along with a specified block size for motion estimation. It computes motion vectors for each block in prev_frame to estimate their motion in next_frame . It returns a list of motion vectors. 2. Load Video and Initialize Variables : o video_capture = cv2.VideoCapture('vb.mov') : Opens the video file named vb.mov . o ret, prev_frame = video_capture.read() : Reads the first frame of the video and stores it in prev_frame .
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
o block_size = 8 : Specifies the size of the blocks for motion estimation. o num_frames = 6 : Defines the number of frames to process. 3. Aggregate Motion Vector Field : o agg_motion_vectors = np.zeros((prev_frame.shape[0] // block_size, prev_frame.shape[1] // block_size, 2), dtype=np.float32) : Initializes an aggregate motion vector field to store cumulative motion vectors. 4. Loop Over Frames : o A loop iterates over subsequent frames (up to num_frames ). 5. Motion Estimation : o motion_vectors = EBMA_motion_estimation(cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY), cv2.cvtColor(next_frame, cv2.COLOR_BGR2GRAY), block_size) : Calls the EBMA_motion_estimation function to estimate motion vectors. 6. Update Aggregate Motion Vector Field : o For each block in the current frame, the corresponding motion vector is added to the aggregate motion vector field. 7. Create Motion Vector Image : o motion_vector_image = np.ones((agg_motion_vectors.shape[0] * block_size, agg_motion_vectors.shape[1] * block_size, 3), dtype=np.uint8) * 255 : Creates a white canvas to visualize motion vectors. 8. Draw Motion Vectors : o A black arrow is drawn for each motion vector on the canvas. If a motion vector points at a 135-degree angle (indicating no clear direction), it is made extremely small ( dx = dy = 0.1 ). 9. Display Frames and Motion Vector Image : o Matplotlib is used to create a figure with subplots. The frames and the motion vector image are displayed.