OpenCV 小ネタ集4
Object detections
- matchTemplate
import cv2 import numpy as np import matplotlib.pyplot as plt def cv2_imshow(title, image): plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) plt.title(title) # as opencv loads in BGR format by default, we want to show it in RGB. plt.show() # Load input image and convert to grayscale image = cv2.imread('./images/WaldoBeach.jpg') cv2_imshow('Where is Waldo?', image) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Load Template image # Load Gray scale template = cv2.imread('./images/waldo.jpg',0) cv2_imshow('Template is gray scale', template) result = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) #Create Bounding Box top_left = max_loc bottom_right = (top_left[0] + 50, top_left[1] + 50) cv2.rectangle(image, top_left, bottom_right, (0,0,255), 5) cv2_imshow('Where is Waldo?', image)
Corners
Corner だけでは、画像が明るくなった場合や scale が違う場合に物体の特徴を検出できない
- cornerHarris
import cv2 import numpy as np import matplotlib.pyplot as plt def cv2_imshow(title, image): plt.figure(figsize=(8, 8)) plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) plt.title(title) # as opencv loads in BGR format by default, we want to show it in RGB. plt.show() # Load image then grayscale image = cv2.imread('images/chess.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # The cornerHarris function requires the array datatype to be float32 gray = np.float32(gray) harris_corners = cv2.cornerHarris(gray, 3, 3, 0.05) #We use dilation of the corner points to enlarge them # cornerHarris kernel = np.ones((7,7),np.uint8) harris_corners = cv2.dilate(harris_corners, kernel, iterations = 2) # Threshold for an optimal value, it may vary depending on the image. image[harris_corners > 0.025 * harris_corners.max() ] = [255, 127, 127] cv2_imshow('Harris Corners', image)
- goodFeaturesToTrack (cornerHarris を改善している。)
import cv2 import numpy as np img = cv2.imread('images/chess.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # We specific the top 50 corners corners = cv2.goodFeaturesToTrack(gray, 150, 0.01, 10) for corner in corners: x, y = corner[0] x = int(x) y = int(y) cv2.rectangle(img,(x-10,y-10),(x+10,y+10),(0,255,0), 2) cv2_imshow("Corners Found", img)
Feature Detection
SIFT or SURF は特許が取得されているため、ただで商用利用できない。ので、使わない。
- ORF
import cv2 import numpy as np import matplotlib.pyplot as plt def cv2_imshow(title, image): plt.figure(figsize=(8, 8)) plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) plt.title(title) # as opencv loads in BGR format by default, we want to show it in RGB. plt.show() image = cv2.imread('images/input.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Create ORB object, we can specify the number of key points we desire orb = cv2.ORB_create() # Determine key points keypoints = orb.detect(gray, None) # Obtain the descriptors keypoints, descriptors = orb.compute(gray, keypoints) print("Number of keypoints Detected: ", len(keypoints)) # Draw rich keypoints on input image image = cv2.drawKeypoints(image, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) cv2_imshow('Feature Method - ORB', image)
import cv2 import numpy as np def ORB_detector(new_image, image_template): # Function that compares input image to template # It then returns the number of ORB matches between them image1 = cv2.cvtColor(new_image, cv2.COLOR_BGR2GRAY) # Create ORB detector with 1000 keypoints with a scaling pyramid factor of 1.2 orb = cv2.ORB(1000, 1.2) # Detect keypoints of original image (kp1, des1) = orb.detectAndCompute(image1, None) # Detect keypoints of rotated image (kp2, des2) = orb.detectAndCompute(image_template, None) # Create matcher # Note we're no longer using Flannbased matching bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # Do matching matches = bf.match(des1,des2) # Sort the matches based on distance. Least distance # is better matches = sorted(matches, key=lambda val: val.distance) return len(matches) cap = cv2.VideoCapture(0) # Load our image template, this is our reference image image_template = cv2.imread('images/box_in_scene.png', 0) # image_template = cv2.imread('images/kitkat.jpg', 0) while True: # Get webcam images ret, frame = cap.read() # Get height and width of webcam frame height, width = frame.shape[:2] # Define ROI Box Dimensions (Note some of these things should be outside the loop) top_left_x = width / 3 top_left_y = (height / 2) + (height / 4) bottom_right_x = (width / 3) * 2 bottom_right_y = (height / 2) - (height / 4) # Draw rectangular window for our region of interest cv2.rectangle(frame, (top_left_x,top_left_y), (bottom_right_x,bottom_right_y), 255, 3) # Crop window of observation we defined above cropped = frame[bottom_right_y:top_left_y , top_left_x:bottom_right_x] # Flip frame orientation horizontally frame = cv2.flip(frame,1) # Get number of ORB matches matches = ORB_detector(cropped, image_template) # Display status string showing the current no. of matches output_string = "Matches = " + str(matches) cv2.putText(frame, output_string, (50,450), cv2.FONT_HERSHEY_COMPLEX, 2, (250,0,150), 2) # Our threshold to indicate object deteciton # For new images or lightening conditions you may need to experiment a bit # Note: The ORB detector to get the top 1000 matches, 350 is essentially a min 35% match threshold = 350 # If matches exceed our threshold then object has been detected if matches > threshold: cv2.rectangle(frame, (top_left_x,top_left_y), (bottom_right_x,bottom_right_y), (0,255,0), 3) cv2.putText(frame,'Object Found',(50,50), cv2.FONT_HERSHEY_COMPLEX, 2 ,(0,255,0), 2) cv2.imshow('Object Detector using ORB', frame) if cv2.waitKey(1) == 13: #13 is the Enter Key break cap.release() cv2.destroyAllWindows()
HOG 記述子
import numpy as np import cv2 import matplotlib.pyplot as plt def cv2_imshow(title, image): plt.figure(figsize=(8, 8)) plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) plt.title(title) # as opencv loads in BGR format by default, we want to show it in RGB. plt.show() # Load image then grayscale image = cv2.imread('images/elephant.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Show original Image cv2_imshow('Input Image', image) # h x w in pixels cell_size = (8, 8) # h x w in cells block_size = (2, 2) # number of orientation bins nbins = 9 # Using OpenCV's HOG Descriptor # winSize is the size of the image cropped to a multiple of the cell size hog = cv2.HOGDescriptor(_winSize=(gray.shape[1] // cell_size[1] * cell_size[1], gray.shape[0] // cell_size[0] * cell_size[0]), _blockSize=(block_size[1] * cell_size[1], block_size[0] * cell_size[0]), _blockStride=(cell_size[1], cell_size[0]), _cellSize=(cell_size[1], cell_size[0]), _nbins=nbins) # Create numpy array shape which we use to create hog_feats n_cells = (gray.shape[0] // cell_size[0], gray.shape[1] // cell_size[1]) # We index blocks by rows first. # hog_feats now contains the gradient amplitudes for each direction, # for each cell of its group for each group. Indexing is by rows then columns. hog_feats = hog.compute(gray).reshape(n_cells[1] - block_size[1] + 1, n_cells[0] - block_size[0] + 1, block_size[0], block_size[1], nbins).transpose((1, 0, 2, 3, 4)) # Create our gradients array with nbin dimensions to store gradient orientations gradients = np.zeros((n_cells[0], n_cells[1], nbins)) # Create array of dimensions cell_count = np.full((n_cells[0], n_cells[1], 1), 0, dtype=int) # Block Normalization for off_y in range(block_size[0]): for off_x in range(block_size[1]): gradients[off_y:n_cells[0] - block_size[0] + off_y + 1, off_x:n_cells[1] - block_size[1] + off_x + 1] += \ hog_feats[:, :, off_y, off_x, :] cell_count[off_y:n_cells[0] - block_size[0] + off_y + 1, off_x:n_cells[1] - block_size[1] + off_x + 1] += 1 # Average gradients gradients /= cell_count # Plot HOGs using Matplotlib # angle is 360 / nbins * direction for i in range(9): # Plot HOGs using Matplotlib # angle is 360 / nbins * direction plt.figure() color_bins = 5 plt.pcolor(gradients[:, :, i]) plt.gca().invert_yaxis() # 図のアスペクト比を正方形にする plt.gca().set_aspect('equal', adjustable='box') plt.colorbar() plt.show()