├── .gitattributes ├── .gitignore ├── Chapter01 ├── 01_reading_image.py ├── 02_saving_image.py ├── 03_convert_image_format.py ├── 04_image_color_split.py ├── 05_image_color_merge.py ├── 06_image_translation.py ├── 07_image_rotation.py ├── 08_image_scaling.py ├── 09_affine_transformation.py ├── 10_projective_transformation.py ├── 11_image_warping.py └── images │ └── input.jpg ├── Chapter02 ├── 01_2d_convolution.py ├── 02_blurring.py ├── 03_sharpening.py ├── 04_embossing.py ├── 05_embossing_advance.py ├── 06_erosion_dilation.py ├── 07_vignette_filter.py ├── 08_vignette_gaussian.py ├── 09_enhacing_contrast.py ├── 09_enhacing_contrast_2.py └── images │ ├── geometrics_input.png │ ├── house_input.png │ ├── image_02_008.png │ ├── sign_input.png │ ├── text_input.png │ ├── train_input.png │ └── tree_input.png ├── Chapter03 ├── 01_accessing_webcam.py ├── 02_keyboard_inputs.py ├── 03_mouse_inputs.py ├── 04_interacting_video.py ├── 05_cartoonizing.py ├── 06_median_filter.py ├── 07_gaussian_bilateral_filter.py └── images │ ├── blue_carpet.png │ └── green_dots.png ├── Chapter04 ├── cascade_files │ ├── haarcascade_eye.xml │ ├── haarcascade_frontalface_alt.xml │ ├── haarcascade_mcs_leftear.xml │ ├── haarcascade_mcs_mouth.xml │ ├── haarcascade_mcs_nose.xml │ └── haarcascade_mcs_rightear.xml ├── ear_detection.py ├── eye_detection.py ├── face_detection.py ├── fun_with_eye.py ├── fun_with_face.py ├── fun_with_mounth.py ├── images │ ├── mask_hannibal.png │ ├── moustache.png │ └── sunglasses.png ├── mounth_detection.py ├── nose_detection.py ├── pupil_detection.py └── remove_overlay_alpha.py ├── Chapter05 ├── fast_detector.py ├── fast_detector_with_brief_extractor.py ├── good_features.py ├── harris_corners.py ├── images │ ├── box.png │ ├── fishing_house.jpg │ ├── house.jpg │ └── tool.png ├── orb_detector.py ├── sift_detect.py └── surf_detect.py ├── Chapter06 ├── expand_image_by_seam_carving.py ├── images │ ├── beach.jpg │ └── ducks.jpg ├── reduce_image_by_seam_carving.py └── remove_element_by_seam_carving.py ├── Chapter07 ├── best_contour_matching.py ├── censor_shapes.py ├── convexity_defects.py ├── convexity_defects_smoothen.py ├── image_segmentation.py ├── images │ ├── boomerang.png │ ├── convex_shapes.png │ ├── hand_pen.jpg │ ├── random_shapes.png │ ├── road.jpg │ └── shapes.png ├── smoothen contour_polygon.py └── watershed.py ├── Chapter08 ├── background_substraction_GMG.py ├── background_substraction_MOG.py ├── colorspace_tracking.py ├── detect_movement.py ├── feature_tracking.py └── object_tracker.py ├── Chapter09 ├── classify_data.py ├── create_features.py ├── feature_detector.py └── training.py ├── Chapter10 ├── augmented_reality_piramide.py ├── augmented_reality_piramide_v2.py └── pose_estimation.py ├── Chapter11 ├── classify_data.py ├── create_features.py ├── feature_extractor.py ├── images │ ├── multiclass_image.png │ ├── multiclass_image_features.png │ └── test.png └── training.py ├── LICENSE ├── README.md └── Software and hardware list.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /Chapter01/01_reading_image.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | img = cv2.imread('./images/input.jpg') 4 | cv2.imshow('Input image', img) 5 | 6 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/02_saving_image.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | gray_img = cv2.imread('images/input.jpg', cv2.IMREAD_GRAYSCALE) 4 | cv2.imshow('Grayscale', gray_img) 5 | cv2.imwrite('images/output.jpg', gray_img) 6 | 7 | 8 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/03_convert_image_format.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | img = cv2.imread('images/input.jpg') 4 | 5 | cv2.imwrite('images/output.png', img, [cv2.IMWRITE_PNG_COMPRESSION]) -------------------------------------------------------------------------------- /Chapter01/04_image_color_split.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | img = cv2.imread('./images/input.jpg', cv2.IMREAD_COLOR) 4 | gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) 5 | 6 | yuv_img = cv2.cvtColor(img, cv2.COLOR_BGR2YUV) 7 | y,u,v = cv2.split(yuv_img) 8 | 9 | cv2.imshow('Grayscale image', gray_img) 10 | cv2.imshow('Y channel', y) 11 | cv2.imshow('U channel', u) 12 | cv2.imshow('V channel', v) 13 | 14 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/05_image_color_merge.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | img = cv2.imread('./images/input.jpg', cv2.IMREAD_COLOR) 4 | 5 | g,b,r = cv2.split(img) 6 | gbr_img = cv2.merge((g,b,r)) 7 | rbr_img = cv2.merge((r,b,r)) 8 | 9 | cv2.imshow('Original', img) 10 | cv2.imshow('GRB', gbr_img) 11 | cv2.imshow('RBR', rbr_img) 12 | 13 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/06_image_translation.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | num_rows, num_cols = img.shape[:2] 6 | 7 | translation_matrix = np.float32([ [1,0,70], [0,1,110] ]) 8 | img_translation = cv2.warpAffine(img, translation_matrix, (num_cols + 70, num_rows + 110)) 9 | translation_matrix = np.float32([ [1,0,-30], [0,1,-50] ]) 10 | img_translation = cv2.warpAffine(img_translation, translation_matrix, (num_cols + 70 + 30, num_rows + 110 + 50)) 11 | 12 | cv2.imshow('Translation', img_translation) 13 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/07_image_rotation.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | num_rows, num_cols = img.shape[:2] 6 | 7 | translation_matrix = np.float32([ [1,0,int(0.5*num_cols)], [0,1,int(0.5*num_rows)] ]) 8 | rotation_matrix = cv2.getRotationMatrix2D((num_cols, num_rows), 30, 1) 9 | 10 | img_translation = cv2.warpAffine(img, translation_matrix, (2*num_cols, 2*num_rows)) 11 | img_rotation = cv2.warpAffine(img_translation, rotation_matrix, (num_cols*2, num_rows*2)) 12 | 13 | cv2.imshow('Rotation', img_rotation) 14 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/08_image_scaling.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | img = cv2.imread('images/input.jpg') 4 | 5 | img_scaled = cv2.resize(img,None,fx=1.2, fy=1.2, interpolation = cv2.INTER_LINEAR) 6 | cv2.imshow('Scaling - Linear Interpolation', img_scaled) 7 | 8 | img_scaled = cv2.resize(img,None,fx=1.2, fy=1.2, interpolation = cv2.INTER_CUBIC) 9 | cv2.imshow('Scaling - Cubic Interpolation', img_scaled) 10 | 11 | img_scaled = cv2.resize(img,(450, 400), interpolation = cv2.INTER_AREA) 12 | cv2.imshow('Scaling - Skewed Size', img_scaled) 13 | 14 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/09_affine_transformation.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | rows, cols = img.shape[:2] 6 | 7 | src_points = np.float32([[0,0], [cols-1,0], [0,rows-1]]) 8 | dst_points = np.float32([[0,0], [int(0.6*(cols-1)),0], [int(0.4*(cols-1)),rows-1]]) 9 | 10 | affine_matrix = cv2.getAffineTransform(src_points, dst_points) 11 | img_output = cv2.warpAffine(img, affine_matrix, (cols,rows)) 12 | 13 | cv2.imshow('Input', img) 14 | cv2.imshow('Output', img_output) 15 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/10_projective_transformation.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | rows, cols = img.shape[:2] 6 | 7 | src_points = np.float32([[0,0], [cols-1,0], [0,rows-1], [cols-1,rows-1]]) 8 | dst_points = np.float32([[0,0], [cols-1,0], [int(0.33*cols),rows-1], [int(0.66*cols),rows-1]]) 9 | 10 | projective_matrix = cv2.getPerspectiveTransform(src_points, dst_points) 11 | img_output = cv2.warpPerspective(img, projective_matrix, (cols,rows)) 12 | 13 | cv2.imshow('Input', img) 14 | cv2.imshow('Output', img_output) 15 | 16 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/11_image_warping.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import math 4 | 5 | img = cv2.imread('images/input.jpg', cv2.IMREAD_GRAYSCALE) 6 | rows, cols = img.shape 7 | 8 | ##################### 9 | # Vertical wave 10 | 11 | img_output = np.zeros(img.shape, dtype=img.dtype) 12 | 13 | for i in range(rows): 14 | for j in range(cols): 15 | offset_x = int(25.0 * math.sin(2 * 3.14 * i / 180)) 16 | offset_y = 0 17 | if j+offset_x < rows: 18 | img_output[i,j] = img[i,(j+offset_x)%cols] 19 | else: 20 | img_output[i,j] = 0 21 | 22 | cv2.imshow('Input', img) 23 | cv2.imshow('Vertical wave', img_output) 24 | 25 | ##################### 26 | # Horizontal wave 27 | 28 | img_output = np.zeros(img.shape, dtype=img.dtype) 29 | 30 | for i in range(rows): 31 | for j in range(cols): 32 | offset_x = 0 33 | offset_y = int(16.0 * math.sin(2 * 3.14 * j / 150)) 34 | if i+offset_y < rows: 35 | img_output[i,j] = img[(i+offset_y)%rows,j] 36 | else: 37 | img_output[i,j] = 0 38 | 39 | cv2.imshow('Horizontal wave', img_output) 40 | 41 | ##################### 42 | # Both horizontal and vertical 43 | 44 | img_output = np.zeros(img.shape, dtype=img.dtype) 45 | 46 | for i in range(rows): 47 | for j in range(cols): 48 | offset_x = int(20.0 * math.sin(2 * 3.14 * i / 150)) 49 | offset_y = int(20.0 * math.cos(2 * 3.14 * j / 150)) 50 | if i+offset_y < rows and j+offset_x < cols: 51 | img_output[i,j] = img[(i+offset_y)%rows,(j+offset_x)%cols] 52 | else: 53 | img_output[i,j] = 0 54 | 55 | cv2.imshow('Multidirectional wave', img_output) 56 | 57 | ##################### 58 | # Concave effect 59 | 60 | img_output = np.zeros(img.shape, dtype=img.dtype) 61 | 62 | for i in range(rows): 63 | for j in range(cols): 64 | offset_x = int(128.0 * math.sin(2 * 3.14 * i / (2*cols))) 65 | offset_y = 0 66 | if j+offset_x < cols: 67 | img_output[i,j] = img[i,(j+offset_x)%cols] 68 | else: 69 | img_output[i,j] = 0 70 | 71 | cv2.imshow('Concave', img_output) 72 | 73 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter01/images/input.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter01/images/input.jpg -------------------------------------------------------------------------------- /Chapter02/01_2d_convolution.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | rows, cols = img.shape[:2] 6 | 7 | kernel_identity = np.array([[0,0,0], [0,1,0], [0,0,0]]) 8 | kernel_3x3 = np.ones((3,3), np.float32) / 9.0 9 | kernel_5x5 = np.ones((5,5), np.float32) / 25.0 10 | 11 | cv2.imshow('Original', img) 12 | 13 | output = cv2.filter2D(img, -1, kernel_identity) # value -1 is to maintain source image depth 14 | cv2.imshow('Identity filter', output) 15 | 16 | output = cv2.filter2D(img, -1, kernel_3x3) 17 | cv2.imshow('3x3 filter', output) 18 | 19 | output = cv2.filter2D(img, -1, kernel_5x5) 20 | cv2.imshow('5x5 filter', output) 21 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/02_blurring.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | cv2.imshow('Original', img) 6 | 7 | size = 15 8 | 9 | # generating the kernel 10 | kernel_motion_blur = np.zeros((size, size)) 11 | kernel_motion_blur[int((size-1)/2), :] = np.ones(size) 12 | kernel_motion_blur = kernel_motion_blur / size 13 | 14 | # applying the kernel to the input image 15 | output = cv2.filter2D(img, -1, kernel_motion_blur) 16 | 17 | cv2.imshow('Motion Blur', output) 18 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/03_sharpening.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | cv2.imshow('Original', img) 6 | 7 | # generating the kernels 8 | kernel_sharpen_1 = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]]) 9 | kernel_sharpen_2 = np.array([[1,1,1], [1,-7,1], [1,1,1]]) 10 | kernel_sharpen_3 = np.array([[-1,-1,-1,-1,-1], 11 | [-1,2,2,2,-1], 12 | [-1,2,8,2,-1], 13 | [-1,2,2,2,-1], 14 | [-1,-1,-1,-1,-1]]) / 8.0 15 | 16 | # applying different kernels to the input image 17 | output_1 = cv2.filter2D(img, -1, kernel_sharpen_1) 18 | output_2 = cv2.filter2D(img, -1, kernel_sharpen_2) 19 | output_3 = cv2.filter2D(img, -1, kernel_sharpen_3) 20 | 21 | cv2.imshow('Sharpening', output_1) 22 | cv2.imshow('Excessive Sharpening', output_2) 23 | cv2.imshow('Edge Enhancement', output_3) 24 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/04_embossing.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img_emboss_input = cv2.imread('images/input.jpg') 5 | 6 | # generating the kernels 7 | kernel_emboss_1 = np.array([[0,-1,-1], 8 | [1,0,-1], 9 | [1,1,0]]) 10 | kernel_emboss_2 = np.array([[-1,-1,0], 11 | [-1,0,1], 12 | [0,1,1]]) 13 | kernel_emboss_3 = np.array([[1,0,0], 14 | [0,0,0], 15 | [0,0,-1]]) 16 | 17 | # converting the image to grayscale 18 | gray_img = cv2.cvtColor(img_emboss_input,cv2.COLOR_BGR2GRAY) 19 | 20 | # applying the kernels to the grayscale image and adding the offset to produce the shadow 21 | output_1 = cv2.filter2D(gray_img, -1, kernel_emboss_1) + 128 22 | output_2 = cv2.filter2D(gray_img, -1, kernel_emboss_2) + 128 23 | output_3 = cv2.filter2D(gray_img, -1, kernel_emboss_3) + 128 24 | 25 | cv2.imshow('Input', img_emboss_input) 26 | cv2.imshow('Embossing - South West', output_1) 27 | cv2.imshow('Embossing - South East', output_2) 28 | cv2.imshow('Embossing - North West', output_3) 29 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/05_embossing_advance.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/geometric.png', cv2.IMREAD_GRAYSCALE) 5 | rows, cols = img.shape 6 | 7 | # It is used depth of cv2.CV_64F. 8 | sobel_horizontal = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5) 9 | 10 | # Kernel size can be: 1,3,5 or 7. 11 | sobel_vertical = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5) 12 | 13 | laplacian = cv2.Laplacian(img, cv2.CV_64F) 14 | canny = cv2.Canny(img, 50, 240) 15 | 16 | cv2.imshow('Original', img) 17 | cv2.imshow('Sobel horizontal', sobel_horizontal) 18 | cv2.imshow('Sobel vertical', sobel_vertical) 19 | 20 | cv2.imshow('Laplacian', laplacian) 21 | cv2.imshow('Canny', canny) 22 | 23 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/06_erosion_dilation.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg', 0) 5 | 6 | kernel = np.ones((5,5), np.uint8) 7 | 8 | img_erosion = cv2.erode(img, kernel, iterations=1) 9 | img_dilation = cv2.dilate(img, kernel, iterations=1) 10 | 11 | cv2.imshow('Input', img) 12 | cv2.imshow('Erosion', img_erosion) 13 | cv2.imshow('Dilation', img_dilation) 14 | 15 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/07_vignette_filter.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | rows, cols = img.shape[:2] 6 | 7 | # generating vignette mask using Gaussian kernels 8 | kernel_x = cv2.getGaussianKernel(cols,200) 9 | kernel_y = cv2.getGaussianKernel(rows,200) 10 | kernel = kernel_y * kernel_x.T 11 | mask = 255 * kernel / np.linalg.norm(kernel) 12 | output = np.copy(img) 13 | 14 | # applying the mask to each channel in the input image 15 | for i in range(3): 16 | output[:,:,i] = output[:,:,i] * mask 17 | 18 | cv2.imshow('Original', img) 19 | cv2.imshow('Vignette', output) 20 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/08_vignette_gaussian.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | rows, cols = img.shape[:2] 6 | 7 | # generating vignette mask using Gaussian kernels 8 | kernel_x = cv2.getGaussianKernel(int(1.5*cols),200) 9 | kernel_y = cv2.getGaussianKernel(int(1.5*rows),200) 10 | kernel = kernel_y * kernel_x.T 11 | mask = 255 * kernel / np.linalg.norm(kernel) 12 | mask = mask[int(0.5*rows):, int(0.5*cols):] 13 | output = np.copy(img) 14 | 15 | # applying the mask to each channel in the input image 16 | for i in range(3): 17 | output[:,:,i] = output[:,:,i] * mask 18 | 19 | cv2.imshow('Input', img) 20 | cv2.imshow('Vignette with shifted focus', output) 21 | 22 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/09_enhacing_contrast.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg', 0) 5 | 6 | # equalize the histogram of the input image 7 | histeq = cv2.equalizeHist(img) 8 | 9 | cv2.imshow('Input', img) 10 | cv2.imshow('Histogram equalized', histeq) 11 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/09_enhacing_contrast_2.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | 6 | img_yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV) 7 | 8 | # equalize the histogram of the Y channel 9 | img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0]) 10 | 11 | # convert the YUV image back to RGB format 12 | img_output = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR) 13 | 14 | cv2.imshow('Color input image', img) 15 | cv2.imshow('Histogram equalized', img_output) 16 | 17 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter02/images/geometrics_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter02/images/geometrics_input.png -------------------------------------------------------------------------------- /Chapter02/images/house_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter02/images/house_input.png -------------------------------------------------------------------------------- /Chapter02/images/image_02_008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter02/images/image_02_008.png -------------------------------------------------------------------------------- /Chapter02/images/sign_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter02/images/sign_input.png -------------------------------------------------------------------------------- /Chapter02/images/text_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter02/images/text_input.png -------------------------------------------------------------------------------- /Chapter02/images/train_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter02/images/train_input.png -------------------------------------------------------------------------------- /Chapter02/images/tree_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter02/images/tree_input.png -------------------------------------------------------------------------------- /Chapter03/01_accessing_webcam.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | cap = cv2.VideoCapture(0) 4 | 5 | # Check if the webcam is opened correctly 6 | if not cap.isOpened(): 7 | raise IOError("Cannot open webcam") 8 | 9 | while True: 10 | ret, frame = cap.read() 11 | frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA) 12 | cv2.imshow('Input', frame) 13 | 14 | c = cv2.waitKey(1) 15 | if c == 27: 16 | break 17 | 18 | cap.release() 19 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter03/02_keyboard_inputs.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | def print_howto(): 4 | print(""" 5 | Change color space of the 6 | input video stream using keyboard controls. The control keys are: 7 | 1. Grayscale - press 'g' 8 | 2. YUV - press 'y' 9 | 3. HSV - press 'h' 10 | """) 11 | 12 | if __name__=='__main__': 13 | print_howto() 14 | cap = cv2.VideoCapture(0) 15 | 16 | # Check if the webcam is opened correctly 17 | if not cap.isOpened(): 18 | raise IOError("Cannot open webcam") 19 | 20 | cur_mode = None 21 | while True: 22 | # Read the current frame from webcam 23 | ret, frame = cap.read() 24 | 25 | # Resize the captured image 26 | frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA) 27 | 28 | c = cv2.waitKey(1) 29 | if c == 27: 30 | break 31 | 32 | if c != -1 and c != 255 and c != cur_mode: 33 | cur_mode = c 34 | 35 | if cur_mode == ord('g'): 36 | output = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 37 | elif cur_mode == ord('y'): 38 | output = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV) 39 | elif cur_mode == ord('h'): 40 | output = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 41 | else: 42 | output = frame 43 | cv2.imshow('Webcam', output) 44 | 45 | cap.release() 46 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter03/03_mouse_inputs.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | def detect_quadrant(event, x, y, flags, param): 5 | if event == cv2.EVENT_LBUTTONDOWN: 6 | if x > width/2: 7 | if y > height/2: 8 | point_top_left = (int(width/2), int(height/2)) 9 | point_bottom_right = (width-1, height-1) 10 | else: 11 | point_top_left = (int(width/2), 0) 12 | point_bottom_right = (width-1, int(height/2)) 13 | 14 | else: 15 | if y > height/2: 16 | point_top_left = (0, int(height/2)) 17 | point_bottom_right = (int(width/2), height-1) 18 | else: 19 | point_top_left = (0, 0) 20 | point_bottom_right = (int(width/2), int(height/2)) 21 | 22 | img = param["img"] 23 | # Repaint all in white again 24 | cv2.rectangle(img, (0,0), (width-1,height-1), (255,255,255), -1) 25 | # Paint green quadrant 26 | cv2.rectangle(img, point_top_left, point_bottom_right, (0,100,0), -1) 27 | 28 | if __name__=='__main__': 29 | width, height = 640, 480 30 | img = 255 * np.ones((height, width, 3), dtype=np.uint8) 31 | cv2.namedWindow('Input window') 32 | cv2.setMouseCallback('Input window', detect_quadrant, {"img": img}) 33 | 34 | while True: 35 | cv2.imshow('Input window', img) 36 | c = cv2.waitKey(1) 37 | if c == 27: 38 | break 39 | 40 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter03/04_interacting_video.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | def draw_rectangle(event, x, y, flags, params): 5 | global x_init, y_init, drawing 6 | def update_pts(): 7 | params["top_left_pt"] = (min(x_init, x), min(y_init, y)) 8 | params["bottom_right_pt"] = (max(x_init, x), max(y_init, y)) 9 | img[y_init:y, x_init:x] = 255 - img[y_init:y, x_init:x] 10 | if event == cv2.EVENT_LBUTTONDOWN: 11 | drawing = True 12 | x_init, y_init = x, y 13 | 14 | elif event == cv2.EVENT_MOUSEMOVE and drawing: 15 | update_pts() 16 | 17 | elif event == cv2.EVENT_LBUTTONUP: 18 | drawing = False 19 | update_pts() 20 | 21 | if __name__=='__main__': 22 | drawing = False 23 | event_params = {"top_left_pt": (-1, -1), "bottom_right_pt": (-1, -1)} 24 | 25 | cap = cv2.VideoCapture(0) 26 | 27 | # Check if the webcam is opened correctly 28 | if not cap.isOpened(): 29 | raise IOError("Cannot open webcam") 30 | 31 | cv2.namedWindow('Webcam') 32 | cv2.setMouseCallback('Webcam', draw_rectangle, event_params) 33 | 34 | while True: 35 | ret, frame = cap.read() 36 | img = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA) 37 | (x0,y0), (x1,y1) = event_params["top_left_pt"], event_params["bottom_right_pt"] 38 | img[y0:y1, x0:x1] = 255 - img[y0:y1, x0:x1] 39 | cv2.imshow('Webcam', img) 40 | 41 | c = cv2.waitKey(1) 42 | if c == 27: 43 | break 44 | 45 | cap.release() 46 | cv2.destroyAllWindows() 47 | -------------------------------------------------------------------------------- /Chapter03/05_cartoonizing.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | def print_howto(): 5 | print(""" 6 | Change cartoonizing mode of image: 7 | 1. Cartoonize without Color - press 's' 8 | 2. Cartoonize with Color - press 'c' 9 | """) 10 | 11 | def cartoonize_image(img, ksize=5, sketch_mode=False): 12 | num_repetitions, sigma_color, sigma_space, ds_factor = 10, 5, 7, 4 13 | # Convert image to grayscale 14 | img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 15 | 16 | # Apply median filter to the grayscale image 17 | img_gray = cv2.medianBlur(img_gray, 7) 18 | 19 | # Detect edges in the image and threshold it 20 | edges = cv2.Laplacian(img_gray, cv2.CV_8U, ksize=ksize) 21 | ret, mask = cv2.threshold(edges, 100, 255, cv2.THRESH_BINARY_INV) 22 | 23 | # 'mask' is the sketch of the image 24 | if sketch_mode: 25 | return cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) 26 | 27 | # Resize the image to a smaller size for faster computation 28 | img_small = cv2.resize(img, None, fx=1.0/ds_factor, fy=1.0/ds_factor, interpolation=cv2.INTER_AREA) 29 | 30 | # Apply bilateral filter the image multiple times 31 | for i in range(num_repetitions): 32 | img_small = cv2.bilateralFilter(img_small, ksize, sigma_color, sigma_space) 33 | 34 | img_output = cv2.resize(img_small, None, fx=ds_factor, fy=ds_factor, interpolation=cv2.INTER_LINEAR) 35 | 36 | dst = np.zeros(img_gray.shape) 37 | 38 | # Add the thick boundary lines to the image using 'AND' operator 39 | dst = cv2.bitwise_and(img_output, img_output, mask=mask) 40 | return dst 41 | 42 | if __name__=='__main__': 43 | print_howto() 44 | cap = cv2.VideoCapture(0) 45 | 46 | cur_mode = None 47 | while True: 48 | ret, frame = cap.read() 49 | frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA) 50 | 51 | c = cv2.waitKey(1) 52 | if c == 27: 53 | break 54 | 55 | if c != -1 and c != 255 and c != cur_mode: 56 | cur_mode = c 57 | 58 | if cur_mode == ord('s'): 59 | cv2.imshow('Cartoonize', cartoonize_image(frame, ksize=5, sketch_mode=True)) 60 | elif cur_mode == ord('c'): 61 | cv2.imshow('Cartoonize', cartoonize_image(frame, ksize=5, sketch_mode=False)) 62 | else: 63 | cv2.imshow('Cartoonize', frame) 64 | 65 | cap.release() 66 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter03/06_median_filter.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | output = cv2.medianBlur(img, ksize=7) 6 | cv2.imshow('Input', img) 7 | cv2.imshow('Median filter', output) 8 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter03/07_gaussian_bilateral_filter.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/input.jpg') 5 | 6 | img_gaussian = cv2.GaussianBlur(img, (13,13), 0) 7 | img_bilateral = cv2.bilateralFilter(img, 13, 70, 50) 8 | 9 | cv2.imshow('Input', img) 10 | cv2.imshow('Gaussian filter', img_gaussian) 11 | cv2.imshow('Bilateral filter', img_bilateral) 12 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter03/images/blue_carpet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter03/images/blue_carpet.png -------------------------------------------------------------------------------- /Chapter03/images/green_dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter03/images/green_dots.png -------------------------------------------------------------------------------- /Chapter04/cascade_files/haarcascade_mcs_leftear.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter04/cascade_files/haarcascade_mcs_leftear.xml -------------------------------------------------------------------------------- /Chapter04/cascade_files/haarcascade_mcs_rightear.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter04/cascade_files/haarcascade_mcs_rightear.xml -------------------------------------------------------------------------------- /Chapter04/ear_detection.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | left_ear_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_mcs_leftear.xml') 5 | right_ear_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_mcs_rightear.xml') 6 | 7 | if left_ear_cascade.empty(): 8 | raise IOError('Unable to load the left ear cascade classifier xml file') 9 | 10 | if right_ear_cascade.empty(): 11 | raise IOError('Unable to load the right ear cascade classifier xml file') 12 | 13 | cap = cv2.VideoCapture(1) 14 | scaling_factor = 0.5 15 | while True: 16 | ret, frame = cap.read() 17 | frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA) 18 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 19 | 20 | left_ear = left_ear_cascade.detectMultiScale(gray, scaleFactor=1.7, minNeighbors=3) 21 | right_ear = right_ear_cascade.detectMultiScale(gray, scaleFactor=1.7, minNeighbors=3) 22 | 23 | for (x,y,w,h) in left_ear: 24 | cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 3) 25 | 26 | for (x,y,w,h) in right_ear: 27 | cv2.rectangle(frame, (x,y), (x+w,y+h), (255,0,0), 3) 28 | 29 | cv2.imshow('Ear Detector', frame) 30 | c = cv2.waitKey(1) 31 | if c == 27: 32 | break 33 | 34 | cap.release() 35 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/eye_detection.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | face_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_frontalface_alt.xml') 5 | eye_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_eye.xml') 6 | if face_cascade.empty(): 7 | raise IOError('Unable to load the face cascade classifier xml file') 8 | 9 | if eye_cascade.empty(): 10 | raise IOError('Unable to load the eye cascade classifier xml file') 11 | 12 | cap = cv2.VideoCapture(0) 13 | ds_factor = 0.5 14 | 15 | while True: 16 | ret, frame = cap.read() 17 | frame = cv2.resize(frame, None, fx=ds_factor, fy=ds_factor, interpolation=cv2.INTER_AREA) 18 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 19 | 20 | faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=1) 21 | for (x,y,w,h) in faces: 22 | roi_gray = gray[y:y+h, x:x+w] 23 | roi_color = frame[y:y+h, x:x+w] 24 | eyes = eye_cascade.detectMultiScale(roi_gray) 25 | for (x_eye,y_eye,w_eye,h_eye) in eyes: 26 | center = (int(x_eye + 0.5*w_eye), int(y_eye + 0.5*h_eye)) 27 | radius = int(0.3 * (w_eye + h_eye)) 28 | color = (0, 255, 0) 29 | thickness = 3 30 | cv2.circle(roi_color, center, radius, color, thickness) 31 | 32 | cv2.imshow('Eye Detector', frame) 33 | 34 | c = cv2.waitKey(1) 35 | if c == 27: 36 | break 37 | 38 | cap.release() 39 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/face_detection.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | face_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_frontalface_alt.xml') 5 | 6 | cap = cv2.VideoCapture(1) 7 | scaling_factor = 0.5 8 | 9 | while True: 10 | ret, frame = cap.read() 11 | frame = cv2.resize(frame, None, fx=scaling_factor, 12 | fy=scaling_factor, interpolation=cv2.INTER_AREA) 13 | 14 | face_rects = face_cascade.detectMultiScale(frame, scaleFactor=1.3, minNeighbors=3) 15 | for (x,y,w,h) in face_rects: 16 | cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 3) 17 | 18 | cv2.imshow('Face Detector', frame) 19 | 20 | c = cv2.waitKey(1) 21 | if c == 27: 22 | break 23 | 24 | cap.release() 25 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/fun_with_eye.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | face_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_frontalface_alt.xml') 5 | eye_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_eye.xml') 6 | 7 | if face_cascade.empty(): 8 | raise IOError('Unable to load the face cascade classifier xml file') 9 | if eye_cascade.empty(): 10 | raise IOError('Unable to load the eye cascade classifier xml file') 11 | 12 | cap = cv2.VideoCapture(0) 13 | sunglasses_img = cv2.imread('images/sunglasses.png') 14 | 15 | while True: 16 | ret, frame = cap.read() 17 | frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA) 18 | vh, vw = frame.shape[:2] 19 | vh, vw = int(vh), int(vw) 20 | 21 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 22 | faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=1) 23 | centers = [] 24 | 25 | for (x,y,w,h) in faces: 26 | roi_gray = gray[y:y+h, x:x+w] 27 | roi_color = frame[y:y+h, x:x+w] 28 | eyes = eye_cascade.detectMultiScale(roi_gray) 29 | for (x_eye,y_eye,w_eye,h_eye) in eyes: 30 | centers.append((x + int(x_eye + 0.5*w_eye), y + int(y_eye + 0.5*h_eye))) 31 | 32 | if len(centers) > 1: # if detects both eyes 33 | h, w = sunglasses_img.shape[:2] 34 | # Extract the region of interest from the image 35 | eye_distance = abs(centers[1][0] - centers[0][0]) 36 | # Overlay sunglasses; the factor 2.12 is customizable depending on the size of the face 37 | sunglasses_width = 2.12 * eye_distance 38 | scaling_factor = sunglasses_width / w 39 | print(scaling_factor, eye_distance) 40 | overlay_sunglasses = cv2.resize(sunglasses_img, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA) 41 | 42 | x = centers[0][0] if centers[0][0] < centers[1][0] else centers[1][0] 43 | 44 | # customizable X and Y locations; depends on the size of the face 45 | x -= int(0.26*overlay_sunglasses.shape[1]) 46 | y += int(0.26*overlay_sunglasses.shape[0]) 47 | 48 | h, w = overlay_sunglasses.shape[:2] 49 | h, w = int(h), int(w) 50 | frame_roi = frame[y:y+h, x:x+w] 51 | # Convert color image to grayscale and threshold it 52 | gray_overlay_sunglassess = cv2.cvtColor(overlay_sunglasses, cv2.COLOR_BGR2GRAY) 53 | ret, mask = cv2.threshold(gray_overlay_sunglassess, 180, 255, cv2.THRESH_BINARY_INV) 54 | 55 | # Create an inverse mask 56 | mask_inv = cv2.bitwise_not(mask) 57 | 58 | try: 59 | # Use the mask to extract the face mask region of interest 60 | masked_face = cv2.bitwise_and(overlay_sunglasses, overlay_sunglasses, mask=mask) 61 | # Use the inverse mask to get the remaining part of the image 62 | masked_frame = cv2.bitwise_and(frame_roi, frame_roi, mask=mask_inv) 63 | except cv2.error as e: 64 | print('Ignoring arithmentic exceptions: '+ str(e)) 65 | #raise e 66 | 67 | # add the two images to get the final output 68 | frame[y:y+h, x:x+w] = cv2.add(masked_face, masked_frame) 69 | else: 70 | print('Eyes not detected') 71 | 72 | 73 | cv2.imshow('Eye Detector', frame) 74 | c = cv2.waitKey(1) 75 | if c == 27: 76 | break 77 | 78 | cap.release() 79 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/fun_with_face.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | face_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_frontalface_alt.xml') 5 | 6 | face_mask = cv2.imread('./images/mask_hannibal.png') 7 | h_mask, w_mask = face_mask.shape[:2] 8 | 9 | if face_cascade.empty(): 10 | raise IOError('Unable to load the face cascade classifier xml file') 11 | 12 | cap = cv2.VideoCapture(1) 13 | scaling_factor = 0.5 14 | 15 | while True: 16 | ret, frame = cap.read() 17 | frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA) 18 | 19 | face_rects = face_cascade.detectMultiScale(frame, scaleFactor=1.3, minNeighbors=3) 20 | for (x,y,w,h) in face_rects: 21 | if h <= 0 or w <= 0: pass 22 | # Adjust the height and weight parameters depending on the sizes and the locations. 23 | # You need to play around with these to make sure you get it right. 24 | h, w = int(1.4*h), int(1.0*w) 25 | y -= int(0.1*h) 26 | x = int(x) 27 | 28 | # Extract the region of interest from the image 29 | frame_roi = frame[y:y+h, x:x+w] 30 | face_mask_small = cv2.resize(face_mask, (w, h), interpolation=cv2.INTER_AREA) 31 | 32 | # Convert color image to grayscale and threshold it 33 | gray_mask = cv2.cvtColor(face_mask_small, cv2.COLOR_BGR2GRAY) 34 | ret, mask = cv2.threshold(gray_mask, 180, 255, cv2.THRESH_BINARY_INV) 35 | 36 | # Create an inverse mask 37 | mask_inv = cv2.bitwise_not(mask) 38 | 39 | try: 40 | # Use the mask to extract the face mask region of interest 41 | masked_face = cv2.bitwise_and(face_mask_small, face_mask_small, mask=mask) 42 | # Use the inverse mask to get the remaining part of the image 43 | masked_frame = cv2.bitwise_and(frame_roi, frame_roi, mask=mask_inv) 44 | except cv2.error as e: 45 | print('Ignoring arithmentic exceptions: '+ str(e)) 46 | 47 | # add the two images to get the final output 48 | frame[y:y+h, x:x+w] = cv2.add(masked_face, masked_frame) 49 | 50 | cv2.imshow('Face Detector', frame) 51 | 52 | c = cv2.waitKey(1) 53 | if c == 27: 54 | break 55 | 56 | cap.release() 57 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/fun_with_mounth.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | mouth_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_mcs_mouth.xml') 5 | 6 | moustache_mask = cv2.imread('./images/moustache.png') 7 | h_mask, w_mask = moustache_mask.shape[:2] 8 | 9 | if mouth_cascade.empty(): 10 | raise IOError('Unable to load the mouth cascade classifier xml file') 11 | 12 | cap = cv2.VideoCapture(0) 13 | scaling_factor = 0.5 14 | 15 | while True: 16 | ret, frame = cap.read() 17 | frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA) 18 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 19 | 20 | mouth_rects = mouth_cascade.detectMultiScale(gray, 1.3, 5) 21 | if len(mouth_rects) > 0: 22 | (x,y,w,h) = mouth_rects[0] 23 | h, w = int(0.6*h), int(1.2*w) 24 | x -= int(0.05*w) 25 | y -= int(0.55*h) 26 | frame_roi = frame[y:y+h, x:x+w] 27 | moustache_mask_small = cv2.resize(moustache_mask, (w, h), interpolation=cv2.INTER_AREA) 28 | 29 | gray_mask = cv2.cvtColor(moustache_mask_small, cv2.COLOR_BGR2GRAY) 30 | ret, mask = cv2.threshold(gray_mask, 50, 255, cv2.THRESH_BINARY_INV) 31 | mask_inv = cv2.bitwise_not(mask) 32 | masked_mouth = cv2.bitwise_and(moustache_mask_small, moustache_mask_small, mask=mask) 33 | masked_frame = cv2.bitwise_and(frame_roi, frame_roi, mask=mask_inv) 34 | frame[y:y+h, x:x+w] = cv2.add(masked_mouth, masked_frame) 35 | 36 | cv2.imshow('Moustache', frame) 37 | c = cv2.waitKey(1) 38 | if c == 27: 39 | break 40 | 41 | cap.release() 42 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/images/mask_hannibal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter04/images/mask_hannibal.png -------------------------------------------------------------------------------- /Chapter04/images/moustache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter04/images/moustache.png -------------------------------------------------------------------------------- /Chapter04/images/sunglasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter04/images/sunglasses.png -------------------------------------------------------------------------------- /Chapter04/mounth_detection.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | mouth_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_mcs_mouth.xml') 5 | 6 | if mouth_cascade.empty(): 7 | raise IOError('Unable to load the mouth cascade classifier xml file') 8 | 9 | cap = cv2.VideoCapture(0) 10 | ds_factor = 0.5 11 | 12 | while True: 13 | ret, frame = cap.read() 14 | frame = cv2.resize(frame, None, fx=ds_factor, fy=ds_factor, interpolation=cv2.INTER_AREA) 15 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 16 | 17 | mouth_rects = mouth_cascade.detectMultiScale(gray, scaleFactor=1.7, minNeighbors=11) 18 | for (x,y,w,h) in mouth_rects: 19 | y = int(y - 0.15*h) 20 | cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 3) 21 | break 22 | 23 | cv2.imshow('Mouth Detector', frame) 24 | 25 | c = cv2.waitKey(1) 26 | if c == 27: 27 | break 28 | 29 | cap.release() 30 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/nose_detection.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | nose_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_mcs_nose.xml') 5 | 6 | if nose_cascade.empty(): 7 | raise IOError('Unable to load the nose cascade classifier xml file') 8 | 9 | cap = cv2.VideoCapture(0) 10 | ds_factor = 0.5 11 | 12 | while True: 13 | ret, frame = cap.read() 14 | frame = cv2.resize(frame, None, fx=ds_factor, fy=ds_factor, interpolation=cv2.INTER_AREA) 15 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 16 | 17 | nose_rects = nose_cascade.detectMultiScale(gray, 1.3, 5) 18 | for (x,y,w,h) in nose_rects: 19 | cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 3) 20 | break 21 | 22 | cv2.imshow('Nose Detector', frame) 23 | c = cv2.waitKey(1) 24 | if c == 27: 25 | break 26 | 27 | cap.release() 28 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/pupil_detection.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | import cv2 4 | 5 | eye_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_eye.xml') 6 | if eye_cascade.empty(): 7 | raise IOError('Unable to load the eye cascade classifier xml file') 8 | 9 | cap = cv2.VideoCapture(0) 10 | ds_factor = 0.5 11 | ret, frame = cap.read() 12 | contours = [] 13 | 14 | while True: 15 | ret, frame = cap.read() 16 | frame = cv2.resize(frame, None, fx=ds_factor, fy=ds_factor, interpolation=cv2.INTER_AREA) 17 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 18 | eyes = eye_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=1) 19 | for (x_eye, y_eye, w_eye, h_eye) in eyes: 20 | pupil_frame = gray[y_eye:y_eye + h_eye, x_eye:x_eye + w_eye] 21 | ret, thresh = cv2.threshold(pupil_frame, 80, 255, cv2.THRESH_BINARY) 22 | cv2.imshow("threshold", thresh) 23 | im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 24 | print(contours) 25 | 26 | for contour in contours: 27 | area = cv2.contourArea(contour) 28 | rect = cv2.boundingRect(contour) 29 | x, y, w, h = rect 30 | radius = 0.15 * (w + h) 31 | 32 | area_condition = (100 <= area <= 200) 33 | symmetry_condition = (abs(1 - float(w)/float(h)) <= 0.2) 34 | fill_condition = (abs(1 - (area / (math.pi * math.pow(radius, 2.0)))) <= 0.4) 35 | cv2.circle(frame, (int(x_eye + x + radius), int(y_eye + y + radius)), int(1.3 * radius), (0, 180, 0), -1) 36 | 37 | cv2.imshow('Pupil Detector', frame) 38 | c = cv2.waitKey(1) 39 | if c == 27: 40 | break 41 | 42 | cap.release() 43 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter04/remove_overlay_alpha.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import sys 4 | 5 | def remove_alpha_channel(source): 6 | source_img = cv2.cvtColor(source[:,:,:3], cv2.COLOR_BGR2GRAY) 7 | source_mask = source[:,:,3] * (1 / 255.0) 8 | bg_part = (255 * (1 / 255.0)) * (1.0 - source_mask) 9 | weigh = (source_img * (1 / 255.0)) * (source_mask) 10 | dest = np.uint8(cv2.addWeighted(bg_part, 255.0, weigh, 255.0, 0.0)) 11 | return dest 12 | 13 | if __name__=='__main__': 14 | orig_img = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED) 15 | dest_img = remove_alpha_channel(orig_img) 16 | cv2.imwrite(sys.argv[2], dest_img, [cv2.IMWRITE_PNG_COMPRESSION]) -------------------------------------------------------------------------------- /Chapter05/fast_detector.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | input_image = cv2.imread('images/tool.png') 5 | gray_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY) 6 | 7 | # Version under opencv 3.0.0 cv2.FastFeatureDetector() 8 | fast = cv2.FastFeatureDetector_create() 9 | 10 | # Detect keypoints 11 | keypoints = fast.detect(gray_image, None) 12 | print("Number of keypoints with non max suppression:", len(keypoints)) 13 | 14 | 15 | # Draw keypoints on top of the input image 16 | img_keypoints_with_nonmax=input_image.copy() 17 | cv2.drawKeypoints(input_image, keypoints, img_keypoints_with_nonmax, color=(0,255,0), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 18 | cv2.imshow('FAST keypoints - with non max suppression', img_keypoints_with_nonmax) 19 | 20 | # Disable nonmaxSuppression 21 | fast.setNonmaxSuppression(False) 22 | # Detect keypoints again 23 | keypoints = fast.detect(gray_image, None) 24 | print("Total Keypoints without nonmaxSuppression:", len(keypoints)) 25 | 26 | # Draw keypoints on top of the input image 27 | img_keypoints_without_nonmax=input_image.copy() 28 | cv2.drawKeypoints(input_image, keypoints, img_keypoints_without_nonmax, color=(0,255,0), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 29 | cv2.imshow('FAST keypoints - without non max suppression', img_keypoints_without_nonmax) 30 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter05/fast_detector_with_brief_extractor.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | input_image = cv2.imread('images/house.jpg') 5 | gray_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY) 6 | 7 | # Initiate FAST detector 8 | fast = cv2.FastFeatureDetector_create() 9 | 10 | # Initiate BRIEF extractor, before opencv 3.0.0 use cv2.DescriptorExtractor_create("BRIEF") 11 | brief = cv2.xfeatures2d.BriefDescriptorExtractor_create() 12 | 13 | # find the keypoints with STAR 14 | keypoints = fast.detect(gray_image, None) 15 | 16 | # compute the descriptors with BRIEF 17 | keypoints, descriptors = brief.compute(gray_image, keypoints) 18 | 19 | cv2.drawKeypoints(input_image, keypoints, input_image, color=(0,255,0)) 20 | cv2.imshow('BRIEF keypoints', input_image) 21 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter05/good_features.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('images/box.png') 5 | gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 6 | 7 | corners = cv2.goodFeaturesToTrack(gray, maxCorners=7, qualityLevel=0.05, minDistance=25) 8 | corners = np.float32(corners) 9 | 10 | for item in corners: 11 | x, y = item[0] 12 | cv2.circle(img, (x,y), 5, 255, -1) 13 | 14 | cv2.imshow("Top 'k' features", img) 15 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter05/harris_corners.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | img = cv2.imread('./images/box.png') 5 | gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 6 | 7 | gray = np.float32(gray) 8 | 9 | # To detect only sharp corners 10 | dst = cv2.cornerHarris(gray, blockSize=4, ksize=5, k=0.04) 11 | # Result is dilated for marking the corners 12 | dst = cv2.dilate(dst, None) 13 | 14 | # Threshold for an optimal value, it may vary depending on the image 15 | img[dst > 0.01*dst.max()] = [0,0,0] 16 | cv2.imshow('Harris Corners(only sharp)',img) 17 | 18 | # to detect soft corners 19 | dst = cv2.cornerHarris(gray, blockSize=14, ksize=5, k=0.04) 20 | dst = cv2.dilate(dst, None) 21 | img[dst > 0.01*dst.max()] = [0,0,0] 22 | cv2.imshow('Harris Corners(also soft)',img) 23 | 24 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter05/images/box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter05/images/box.png -------------------------------------------------------------------------------- /Chapter05/images/fishing_house.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter05/images/fishing_house.jpg -------------------------------------------------------------------------------- /Chapter05/images/house.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter05/images/house.jpg -------------------------------------------------------------------------------- /Chapter05/images/tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter05/images/tool.png -------------------------------------------------------------------------------- /Chapter05/orb_detector.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | input_image = cv2.imread('images/fishing_house.jpg') 5 | gray_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY) 6 | 7 | # Initiate ORB object, before opencv 3.0.0 use cv2.ORB() 8 | orb = cv2.ORB_create() 9 | 10 | # find the keypoints with ORB 11 | keypoints = orb.detect(gray_image, None) 12 | 13 | # compute the descriptors with ORB 14 | keypoints, descriptors = orb.compute(gray_image, keypoints) 15 | 16 | # draw only the location of the keypoints without size or orientation 17 | cv2.drawKeypoints(input_image, keypoints, input_image, color=(0,255,0)) 18 | 19 | cv2.imshow('ORB keypoints', input_image) 20 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter05/sift_detect.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | input_image = cv2.imread('images/fishing_house.jpg') 5 | gray_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY) 6 | 7 | # For version opencv < 3.0.0, use cv2.SIFT() 8 | sift = cv2.xfeatures2d.SIFT_create() 9 | keypoints = sift.detect(gray_image, None) 10 | 11 | cv2.drawKeypoints(input_image, keypoints, input_image, flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 12 | 13 | cv2.imshow('SIFT features', input_image) 14 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter05/surf_detect.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | input_image = cv2.imread('images/fishing_house.jpg') 5 | gray_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY) 6 | 7 | # For version opencv < 3.0.0, use cv2.SURF() 8 | surf = cv2.xfeatures2d.SURF_create() 9 | # This threshold controls the number of keypoints 10 | surf.setHessianThreshold(15000) 11 | 12 | keypoints, descriptors = surf.detectAndCompute(gray_image, None) 13 | 14 | cv2.drawKeypoints(input_image, keypoints, input_image, color=(0,255,0), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 15 | 16 | cv2.imshow('SURF features', input_image) 17 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter06/expand_image_by_seam_carving.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | # Draw vertical seam on top of the image 6 | def overlay_vertical_seam(img, seam): 7 | img_seam_overlay = np.copy(img) 8 | 9 | # Extract the list of points from the seam 10 | x_coords, y_coords = np.transpose([(i,int(j)) for i,j in enumerate(seam)]) 11 | 12 | # Draw a green line on the image using the list of points 13 | img_seam_overlay[x_coords, y_coords] = (0,255,0) 14 | return img_seam_overlay 15 | 16 | # Compute the energy matrix from the input image 17 | def compute_energy_matrix(img): 18 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 19 | sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3) 20 | sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3) 21 | abs_sobel_x = cv2.convertScaleAbs(sobel_x) 22 | abs_sobel_y = cv2.convertScaleAbs(sobel_y) 23 | return cv2.addWeighted(abs_sobel_x, 0.5, abs_sobel_y, 0.5, 0) 24 | 25 | # Find the vertical seam 26 | def find_vertical_seam(img, energy): 27 | rows, cols = img.shape[:2] 28 | 29 | # Initialize the seam vector with 0 for each element 30 | seam = np.zeros(img.shape[0]) 31 | 32 | # Initialize distance and edge matrices 33 | dist_to = np.zeros(img.shape[:2]) + float('inf') 34 | dist_to[0,:] = np.zeros(img.shape[1]) 35 | edge_to = np.zeros(img.shape[:2]) 36 | 37 | # Dynamic programming; iterate using double loop and compute 38 | #the paths efficiently 39 | for row in range(rows-1): 40 | for col in range(cols): 41 | if col != 0 and \ 42 | dist_to[row+1, col-1] > dist_to[row, col] + energy[row+1, col-1]: 43 | dist_to[row+1, col-1] = dist_to[row, col] + energy[row+1, col-1] 44 | edge_to[row+1, col-1] = 1 45 | 46 | if dist_to[row+1, col] > dist_to[row, col] + energy[row+1, col]: 47 | dist_to[row+1, col] = dist_to[row, col] + energy[row+1, col] 48 | edge_to[row+1, col] = 0 49 | 50 | if col != cols-1: 51 | if dist_to[row+1, col+1] > dist_to[row, col] + energy[row+1, col+1]: 52 | dist_to[row+1, col+1] = dist_to[row, col] + energy[row+1, col+1] 53 | edge_to[row+1, col+1] = -1 54 | 55 | # Retracing the path 56 | seam[rows-1] = np.argmin(dist_to[rows-1, :]) 57 | for i in (x for x in reversed(range(rows)) if x > 0): 58 | seam[i-1] = seam[i] + edge_to[i, int(seam[i])] 59 | 60 | return seam 61 | 62 | # Add a vertical seam to the image 63 | def add_vertical_seam(img, seam, num_iter): 64 | seam = seam + num_iter 65 | rows, cols = img.shape[:2] 66 | zero_col_mat = np.zeros((rows,1,3), dtype=np.uint8) 67 | img_extended = np.hstack((img, zero_col_mat)) 68 | 69 | for row in range(rows): 70 | for col in range(cols, int(seam[row]), -1): 71 | img_extended[row, col] = img[row, col-1] 72 | 73 | # To insert a value between two columns, take the average 74 | # value of the neighbors. It looks smooth this way and we 75 | # can avoid unwanted artifacts. 76 | for i in range(3): 77 | v1 = img_extended[row, int(seam[row])-1, i] 78 | v2 = img_extended[row, int(seam[row])+1, i] 79 | img_extended[row, int(seam[row]), i] = (int(v1)+int(v2))/2 80 | 81 | return img_extended 82 | 83 | # Remove vertical seam from the image 84 | def remove_vertical_seam(img, seam): 85 | rows, cols = img.shape[:2] 86 | for row in range(rows): 87 | for col in range(int(seam[row]), cols-1): 88 | img[row, col] = img[row, col+1] 89 | 90 | img = img[:, 0:cols-1] 91 | return img 92 | 93 | if __name__=='__main__': 94 | img_input = cv2.imread(sys.argv[1]) 95 | num_seams = int(sys.argv[2]) 96 | 97 | img = np.copy(img_input) 98 | img_output = np.copy(img_input) 99 | img_overlay_seam = np.copy(img_input) 100 | energy = compute_energy_matrix(img) 101 | 102 | for i in range(num_seams): 103 | seam = find_vertical_seam(img, energy) 104 | img_overlay_seam = overlay_vertical_seam(img_overlay_seam, seam) 105 | img = remove_vertical_seam(img, seam) 106 | img_output = add_vertical_seam(img_output, seam, i) 107 | energy = compute_energy_matrix(img) 108 | print('Number of seams added =', i+1) 109 | 110 | cv2.imshow('Input', img_input) 111 | cv2.imshow('Seams', img_overlay_seam) 112 | cv2.imshow('Output', img_output) 113 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter06/images/beach.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter06/images/beach.jpg -------------------------------------------------------------------------------- /Chapter06/images/ducks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter06/images/ducks.jpg -------------------------------------------------------------------------------- /Chapter06/reduce_image_by_seam_carving.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import cv2 4 | import numpy as np 5 | 6 | # Draw vertical seam on top of the image 7 | def overlay_vertical_seam(img, seam): 8 | img_seam_overlay = np.copy(img) 9 | 10 | # Extract the list of points from the seam 11 | x_coords, y_coords = np.transpose([(i,int(j)) for i,j in enumerate(seam)]) 12 | 13 | # Draw a green line on the image using the list of points 14 | img_seam_overlay[x_coords, y_coords] = (0,255,0) 15 | return img_seam_overlay 16 | 17 | # Compute the energy matrix from the input image 18 | def compute_energy_matrix(img): 19 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 20 | 21 | # Compute X derivative of the image 22 | sobel_x = cv2.Sobel(gray,cv2.CV_64F, 1, 0, ksize=3) 23 | 24 | # Compute Y derivative of the image 25 | sobel_y = cv2.Sobel(gray,cv2.CV_64F, 0, 1, ksize=3) 26 | 27 | abs_sobel_x = cv2.convertScaleAbs(sobel_x) 28 | abs_sobel_y = cv2.convertScaleAbs(sobel_y) 29 | 30 | # Return weighted summation of the two images i.e. 0.5*X + 0.5*Y 31 | return cv2.addWeighted(abs_sobel_x, 0.5, abs_sobel_y, 0.5, 0) 32 | 33 | # Find vertical seam in the input image 34 | def find_vertical_seam(img, energy): 35 | rows, cols = img.shape[:2] 36 | 37 | # Initialize the seam vector with 0 for each element 38 | seam = np.zeros(img.shape[0]) 39 | 40 | # Initialize distance and edge matrices 41 | dist_to = np.zeros(img.shape[:2]) + float('inf') 42 | dist_to[0,:] = np.zeros(img.shape[1]) 43 | edge_to = np.zeros(img.shape[:2]) 44 | 45 | # Dynamic programming; iterate using double loop and compute the paths efficiently 46 | for row in range(rows-1): 47 | for col in range(cols): 48 | if col != 0 and dist_to[row+1, col-1] > dist_to[row, col] + energy[row+1, col-1]: 49 | dist_to[row+1, col-1] = dist_to[row, col] + energy[row+1, col-1] 50 | edge_to[row+1, col-1] = 1 51 | 52 | if dist_to[row+1, col] > dist_to[row, col] + energy[row+1, col]: 53 | dist_to[row+1, col] = dist_to[row, col] + energy[row+1, col] 54 | edge_to[row+1, col] = 0 55 | 56 | if col != cols-1 and dist_to[row+1, col+1] > dist_to[row, col] + energy[row+1, col+1]: 57 | dist_to[row+1, col+1] = dist_to[row, col] + energy[row+1, col+1] 58 | edge_to[row+1, col+1] = -1 59 | 60 | # Retracing the path 61 | # Returns the indices of the minimum values along X axis. 62 | seam[rows-1] = np.argmin(dist_to[rows-1, :]) 63 | for i in (x for x in reversed(range(rows)) if x > 0): 64 | seam[i-1] = seam[i] + edge_to[i, int(seam[i])] 65 | 66 | return seam 67 | 68 | # Remove the input vertical seam from the image 69 | def remove_vertical_seam(img, seam): 70 | rows, cols = img.shape[:2] 71 | 72 | # To delete a point, move every point after it one step towards the left 73 | for row in range(rows): 74 | for col in range(int(seam[row]), cols-1): 75 | img[row, col] = img[row, col+1] 76 | 77 | # Discard the last column to create the final output image 78 | img = img[:, 0:cols-1] 79 | return img 80 | 81 | if __name__=='__main__': 82 | # Make sure the size of the input image is reasonable. 83 | # Large images take a lot of time to be processed. 84 | # Recommended size is 640x480. 85 | img_input = cv2.imread(sys.argv[1]) 86 | 87 | # Use a small number to get started. Once you get an 88 | # idea of the processing time, you can use a bigger number. 89 | # To get started, you can set it to 20. 90 | num_seams = int(sys.argv[2]) 91 | 92 | img = np.copy(img_input) 93 | img_overlay_seam = np.copy(img_input) 94 | energy = compute_energy_matrix(img) 95 | 96 | for i in range(num_seams): 97 | seam = find_vertical_seam(img, energy) 98 | img_overlay_seam = overlay_vertical_seam(img_overlay_seam, seam) 99 | img = remove_vertical_seam(img, seam) 100 | energy = compute_energy_matrix(img) 101 | print('Number of seams removed = ', i+1) 102 | 103 | cv2.imshow('Input', img_input) 104 | cv2.imshow('Seams', img_overlay_seam) 105 | cv2.imshow('Output', img) 106 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter06/remove_element_by_seam_carving.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | # Draw rectangle on top of the input image 6 | def draw_rectangle(event, x, y, flags, params): 7 | global x_init, y_init, drawing, top_left_pt, bottom_right_pt, img_orig 8 | 9 | # Detecting a mouse click 10 | if event == cv2.EVENT_LBUTTONDOWN: 11 | drawing = True 12 | x_init, y_init = x, y 13 | 14 | # Detecting mouse movement 15 | elif event == cv2.EVENT_MOUSEMOVE: 16 | if drawing: 17 | top_left_pt, bottom_right_pt = (x_init,y_init), (x,y) 18 | img[y_init:y, x_init:x] = 255 - img_orig[y_init:y, x_init:x] 19 | cv2.rectangle(img, top_left_pt, bottom_right_pt, (0,255,0), 2) 20 | 21 | # Detecting the mouse button up event 22 | elif event == cv2.EVENT_LBUTTONUP: 23 | drawing = False 24 | top_left_pt, bottom_right_pt = (x_init,y_init), (x,y) 25 | 26 | # Create the "negative" film effect for the selected 27 | # region 28 | img[y_init:y, x_init:x] = 255 - img[y_init:y, x_init:x] 29 | 30 | # Draw rectangle around the selected region 31 | cv2.rectangle(img, top_left_pt, bottom_right_pt, (0,255,0), 2) 32 | rect_final = (x_init, y_init, x-x_init, y-y_init) 33 | 34 | # Remove the object in the selected region 35 | remove_object(img_orig, rect_final) 36 | 37 | # Computing the energy matrix using modified algorithm 38 | def compute_energy_matrix_modified(img, rect_roi): 39 | # Compute weighted summation i.e. 0.5*X + 0.5*Y 40 | energy_matrix = compute_energy_matrix(img) 41 | x,y,w,h = rect_roi 42 | 43 | # We want the seams to pass through this region, so make sure the energy values in this region are set to 0 44 | energy_matrix[y:y+h, x:x+w] = 0 45 | 46 | return energy_matrix 47 | 48 | # Compute energy matrix 49 | def compute_energy_matrix(img): 50 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 51 | 52 | # Compute X derivative 53 | sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3) 54 | 55 | # Compute Y derivative 56 | sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3) 57 | abs_sobel_x = cv2.convertScaleAbs(sobel_x) 58 | abs_sobel_y = cv2.convertScaleAbs(sobel_y) 59 | 60 | # Return weighted summation i.e. 0.5*X + 0.5*Y 61 | return cv2.addWeighted(abs_sobel_x, 0.5, abs_sobel_y, 0.5, 0) 62 | 63 | # Find the vertical seam 64 | def find_vertical_seam(img, energy): 65 | rows, cols = img.shape[:2] 66 | 67 | # Initialize the seam vector 68 | seam = np.zeros(img.shape[0]) 69 | 70 | # Initialize the distance and edge matrices 71 | dist_to = np.zeros(img.shape[:2]) + float('inf') 72 | dist_to[0,:] = np.zeros(img.shape[1]) 73 | edge_to = np.zeros(img.shape[:2]) 74 | 75 | # Dynamic programming; using double loop to compute the paths 76 | for row in range(rows-1): 77 | for col in range(cols): 78 | if col != 0 and dist_to[row+1, col-1] > dist_to[row, col] + energy[row+1, col-1]: 79 | dist_to[row+1, col-1] = dist_to[row, col] + energy[row+1, col-1] 80 | edge_to[row+1, col-1] = 1 81 | 82 | if dist_to[row+1, col] > dist_to[row, col] + energy[row+1, col]: 83 | dist_to[row+1, col] = dist_to[row, col] + energy[row+1, col] 84 | edge_to[row+1, col] = 0 85 | 86 | if col != cols-1 and dist_to[row+1, col+1] > dist_to[row, col] + energy[row+1, col+1]: 87 | dist_to[row+1, col+1] = dist_to[row, col] + energy[row+1, col+1] 88 | edge_to[row+1, col+1] = -1 89 | 90 | # Retracing the path 91 | seam[rows-1] = np.argmin(dist_to[rows-1, :]) 92 | for i in (x for x in reversed(range(rows)) if x > 0): 93 | seam[i-1] = seam[i] + edge_to[i, int(seam[i])] 94 | 95 | return seam 96 | 97 | # Add vertical seam to the input image 98 | def add_vertical_seam(img, seam, num_iter): 99 | seam = seam + num_iter 100 | rows, cols = img.shape[:2] 101 | zero_col_mat = np.zeros((rows,1,3), dtype=np.uint8) 102 | img_extended = np.hstack((img, zero_col_mat)) 103 | 104 | for row in range(rows): 105 | for col in range(cols, int(seam[row]), -1): 106 | img_extended[row, col] = img[row, col-1] 107 | 108 | # To insert a value between two columns, take the average 109 | # value of the neighbors. It looks smooth this way and we 110 | # can avoid unwanted artifacts. 111 | for i in range(3): 112 | v1 = img_extended[row, int(seam[row])-1, i] 113 | v2 = img_extended[row, int(seam[row])+1, i] 114 | img_extended[row, int(seam[row]), i] = (int(v1)+int(v2))/2 115 | 116 | return img_extended 117 | 118 | # Remove vertical seam 119 | def remove_vertical_seam(img, seam): 120 | rows, cols = img.shape[:2] 121 | for row in range(rows): 122 | for col in range(int(seam[row]), cols-1): 123 | img[row, col] = img[row, col+1] 124 | 125 | img = img[:, 0:cols-1] 126 | return img 127 | 128 | # Remove the object from the input region of interest 129 | def remove_object(img, rect_roi): 130 | num_seams = rect_roi[2] + 10 131 | energy = compute_energy_matrix_modified(img, rect_roi) 132 | 133 | # Start a loop and rsemove one seam at a time 134 | for i in range(num_seams): 135 | # Find the vertical seam that can be removed 136 | seam = find_vertical_seam(img, energy) 137 | 138 | # Remove that vertical seam 139 | img = remove_vertical_seam(img, seam) 140 | x,y,w,h = rect_roi 141 | 142 | # Compute energy matrix after removing the seam 143 | energy = compute_energy_matrix_modified(img, (x,y,w-i,h)) 144 | print('Number of seams removed =', i+1) 145 | 146 | img_output = np.copy(img) 147 | 148 | # Fill up the region with surrounding values so that the size 149 | # of the image remains unchanged 150 | for i in range(num_seams): 151 | seam = find_vertical_seam(img, energy) 152 | img = remove_vertical_seam(img, seam) 153 | img_output = add_vertical_seam(img_output, seam, i) 154 | energy = compute_energy_matrix(img) 155 | print('Number of seams added =', i+1) 156 | 157 | cv2.imshow('Input', img_input) 158 | cv2.imshow('Output', img_output) 159 | cv2.waitKey() 160 | 161 | if __name__=='__main__': 162 | img_input = cv2.imread(sys.argv[1]) 163 | drawing = False 164 | img = np.copy(img_input) 165 | img_orig = np.copy(img_input) 166 | 167 | cv2.namedWindow('Input') 168 | cv2.setMouseCallback('Input', draw_rectangle) 169 | print('Draw a rectangle onto the object to be removed') 170 | while True: 171 | cv2.imshow('Input', img) 172 | c = cv2.waitKey(10) 173 | if c == 27: 174 | break 175 | 176 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter07/best_contour_matching.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | # Extract all the contours from the image 6 | def get_all_contours(img): 7 | ref_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 8 | ret, thresh = cv2.threshold(ref_gray, 127, 255, 0) 9 | # Find all the contours in the thresholded image. The values 10 | # for the second and third parameters are restricted to a 11 | # certain number of possible values. You can learn more 'findContours' function here: 12 | # http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#findcontours 13 | im2, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE ) 14 | return contours 15 | 16 | # Extract reference contour from the image 17 | def get_ref_contour(img): 18 | contours = get_all_contours(img) 19 | 20 | # Extract the relevant contour based on area ratio. We use the 21 | # area ratio because the main image boundary contour is 22 | # extracted as well and we don't want that. This area ratio 23 | # threshold will ensure that we only take the contour inside the image. 24 | for contour in contours: 25 | area = cv2.contourArea(contour) 26 | img_area = img.shape[0] * img.shape[1] 27 | if 0.05 < area/float(img_area) < 0.8: 28 | return contour 29 | 30 | if __name__=='__main__': 31 | # Boomerang reference image 32 | img1 = cv2.imread(sys.argv[1]) 33 | 34 | # Input image containing all the different shapes 35 | img2 = cv2.imread(sys.argv[2]) 36 | 37 | # Extract the reference contour 38 | ref_contour = get_ref_contour(img1) 39 | 40 | # Extract all the contours from the input image 41 | input_contours = get_all_contours(img2) 42 | 43 | closest_contour = None 44 | min_dist = None 45 | contour_img = img2.copy() 46 | cv2.drawContours(contour_img, input_contours, -1, color=(0,0,0), thickness=3) 47 | cv2.imshow('Contours', contour_img) 48 | # Finding the closest contour 49 | for i, contour in enumerate(input_contours): 50 | # Matching the shapes and taking the closest one using 51 | # Comparison method CV_CONTOURS_MATCH_I3 (second argument) 52 | ret = cv2.matchShapes(ref_contour, contour, 3, 0.0) 53 | print("Contour %d matchs in %f" % (i, ret)) 54 | if min_dist is None or ret < min_dist: 55 | min_dist = ret 56 | closest_contour = contour 57 | 58 | cv2.drawContours(img2, [closest_contour], 0 , color=(0,0,0), thickness=3) 59 | cv2.imshow('Best Matching', img2) 60 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter07/censor_shapes.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | # Extract all the contours from the image 6 | def get_all_contours(img): 7 | ref_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 8 | ret, thresh = cv2.threshold(ref_gray, 127, 255, 0) 9 | im2, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE ) 10 | return contours 11 | 12 | if __name__=='__main__': 13 | # Input image containing all the shapes 14 | img = cv2.imread(sys.argv[1]) 15 | 16 | img_orig = np.copy(img) 17 | input_contours = get_all_contours(img) 18 | solidity_values = [] 19 | 20 | # Compute solidity factors of all the contours 21 | for contour in input_contours: 22 | area_contour = cv2.contourArea(contour) 23 | convex_hull = cv2.convexHull(contour) 24 | area_hull = cv2.contourArea(convex_hull) 25 | solidity = float(area_contour)/area_hull 26 | solidity_values.append(solidity) 27 | 28 | # Clustering using KMeans 29 | criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) 30 | flags = cv2.KMEANS_RANDOM_CENTERS 31 | solidity_values = np.array(solidity_values).reshape((len(solidity_values),1)).astype('float32') 32 | compactness, labels, centers = cv2.kmeans(solidity_values, 2, None, criteria, 10, flags) 33 | 34 | closest_class = np.argmin(centers) 35 | output_contours = [] 36 | for i in solidity_values[labels==closest_class]: 37 | index = np.where(solidity_values==i)[0][0] 38 | output_contours.append(input_contours[index]) 39 | 40 | cv2.drawContours(img, output_contours, -1, (0,0,0), 3) 41 | cv2.imshow('Output', img) 42 | 43 | # Censoring 44 | for contour in output_contours: 45 | rect = cv2.minAreaRect(contour) 46 | box = cv2.boxPoints(rect) 47 | box = np.int0(box) 48 | cv2.drawContours(img_orig,[box],0, (0,0,0), -1) 49 | 50 | cv2.imshow('Censored', img_orig) 51 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter07/convexity_defects.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | # Extract all the contours from the image 6 | def get_all_contours(img): 7 | ref_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 8 | ret, thresh = cv2.threshold(ref_gray, 127, 255, 0) 9 | im2, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE ) 10 | return contours 11 | 12 | if __name__=='__main__': 13 | img = cv2.imread(sys.argv[1]) 14 | 15 | # Iterate over the extracted contours 16 | for contour in get_all_contours(img): 17 | # Extract convex hull from the contour 18 | hull = cv2.convexHull(contour, returnPoints=False) 19 | 20 | # Extract convexity defects from the above hull 21 | defects = cv2.convexityDefects(contour, hull) 22 | 23 | if defects is None: 24 | continue 25 | 26 | # Draw lines and circles to show the defects 27 | for i in range(defects.shape[0]): 28 | start_defect, end_defect, far_defect, _ = defects[i,0] 29 | start = tuple(contour[start_defect][0]) 30 | end = tuple(contour[end_defect][0]) 31 | far = tuple(contour[far_defect][0]) 32 | cv2.circle(img, far, 5, [128,0,0], -1) 33 | cv2.drawContours(img, [contour], -1, color=(0,0,0), thickness=3) 34 | 35 | cv2.imshow('Convexity defects',img) 36 | cv2.waitKey(0) 37 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter07/convexity_defects_smoothen.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | # Extract all the contours from the image 6 | def get_all_contours(img): 7 | ref_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 8 | ret, thresh = cv2.threshold(ref_gray, 127, 255, 0) 9 | im2, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE ) 10 | return contours 11 | 12 | if __name__=='__main__': 13 | img = cv2.imread(sys.argv[1]) 14 | factor = 0.01 15 | # Iterate over the extrqcted contours 16 | for contour in get_all_contours(img): 17 | orig_contour = contour 18 | epsilon = factor * cv2.arcLength(contour, True) 19 | contour = cv2.approxPolyDP(contour, epsilon, True) 20 | 21 | # Extract convex hull and the convexity defects 22 | hull = cv2.convexHull(contour, returnPoints=False) 23 | defects = cv2.convexityDefects(contour,hull) 24 | 25 | if defects is None: 26 | continue 27 | 28 | # Draw lines and circles to show the defects 29 | for i in range(defects.shape[0]): 30 | start_defect, end_defect, far_defect, _ = defects[i,0] 31 | start = tuple(contour[start_defect][0]) 32 | end = tuple(contour[end_defect][0]) 33 | far = tuple(contour[far_defect][0]) 34 | cv2.circle(img, far, 7, [255,0,0], -1) 35 | cv2.drawContours(img, [orig_contour], -1, color=(0,0,0), thickness=2) 36 | cv2.drawContours(img, [contour], -1, color=(255,0,0), thickness=2) 37 | 38 | cv2.imshow('Convexity defects',img) 39 | cv2.waitKey(0) 40 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter07/image_segmentation.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | # Draw rectangle based on the input selection 6 | def draw_rectangle(event, x, y, flags, params): 7 | global x_init, y_init, drawing, top_left_pt, bottom_right_pt, img_orig 8 | 9 | # Detecting mouse button down event 10 | if event == cv2.EVENT_LBUTTONDOWN: 11 | drawing = True 12 | x_init, y_init = x, y 13 | 14 | # Detecting mouse movement 15 | elif event == cv2.EVENT_MOUSEMOVE: 16 | if drawing: 17 | top_left_pt, bottom_right_pt = (x_init,y_init), (x,y) 18 | img[y_init:y, x_init:x] = 255 - img_orig[y_init:y, x_init:x] 19 | cv2.rectangle(img, top_left_pt, bottom_right_pt, (0,255,0), 2) 20 | 21 | # Detecting mouse button up event 22 | elif event == cv2.EVENT_LBUTTONUP: 23 | drawing = False 24 | top_left_pt, bottom_right_pt = (x_init,y_init), (x,y) 25 | img[y_init:y, x_init:x] = 255 - img[y_init:y, x_init:x] 26 | cv2.rectangle(img, top_left_pt, bottom_right_pt, (0,255,0), 2) 27 | rect_final = (x_init, y_init, x-x_init, y-y_init) 28 | 29 | # Run Grabcut on the region of interest 30 | run_grabcut(img_orig, rect_final) 31 | 32 | # Grabcut algorithm 33 | def run_grabcut(img_orig, rect_final): 34 | # Initialize the mask 35 | mask = np.zeros(img_orig.shape[:2],np.uint8) 36 | 37 | # Extract the rectangle and set the region of 38 | # interest in the above mask 39 | x,y,w,h = rect_final 40 | mask[y:y+h, x:x+w] = 1 41 | 42 | # Initialize background and foreground models 43 | bgdModel = np.zeros((1,65), np.float64) 44 | fgdModel = np.zeros((1,65), np.float64) 45 | 46 | # Run Grabcut algorithm 47 | cv2.grabCut(img_orig, mask, rect_final, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) 48 | 49 | # Extract new mask 50 | mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8') 51 | 52 | # Apply the above mask to the image 53 | img_orig = img_orig*mask2[:,:,np.newaxis] 54 | 55 | # Display the image 56 | cv2.imshow('Output', img_orig) 57 | 58 | if __name__=='__main__': 59 | drawing = False 60 | top_left_pt, bottom_right_pt = (-1,-1), (-1,-1) 61 | 62 | # Read the input image 63 | img_orig = cv2.imread(sys.argv[1]) 64 | img = img_orig.copy() 65 | 66 | cv2.namedWindow('Input') 67 | cv2.setMouseCallback('Input', draw_rectangle) 68 | 69 | while True: 70 | cv2.imshow('Input', img) 71 | c = cv2.waitKey(1) 72 | if c == 27: 73 | break 74 | 75 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter07/images/boomerang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter07/images/boomerang.png -------------------------------------------------------------------------------- /Chapter07/images/convex_shapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter07/images/convex_shapes.png -------------------------------------------------------------------------------- /Chapter07/images/hand_pen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter07/images/hand_pen.jpg -------------------------------------------------------------------------------- /Chapter07/images/random_shapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter07/images/random_shapes.png -------------------------------------------------------------------------------- /Chapter07/images/road.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter07/images/road.jpg -------------------------------------------------------------------------------- /Chapter07/images/shapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/OpenCV-3-x-with-Python-By-Example/e99a98951297defc3c7e29c1b140b0c127369972/Chapter07/images/shapes.png -------------------------------------------------------------------------------- /Chapter07/smoothen contour_polygon.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | # Extract all the contours from the image 6 | def get_all_contours(img): 7 | ref_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 8 | ret, thresh = cv2.threshold(ref_gray, 127, 255, 0) 9 | im2, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE ) 10 | return contours 11 | 12 | if __name__=='__main__': 13 | # Input image containing all the different shapes 14 | img1 = cv2.imread(sys.argv[1]) 15 | # Extract all the contours from the input image 16 | input_contours = get_all_contours(img1) 17 | 18 | contour_img = img1.copy() 19 | smoothen_contours = [] 20 | factor = 0.01 21 | 22 | # Finding the closest contour 23 | for contour in input_contours: 24 | epsilon = factor * cv2.arcLength(contour, True) 25 | smoothen_contours.append(cv2.approxPolyDP(contour, epsilon, True)) 26 | 27 | cv2.drawContours(contour_img, smoothen_contours, -1, color=(0,0,0), thickness=3) 28 | cv2.imshow('Contours', contour_img) 29 | cv2.waitKey() -------------------------------------------------------------------------------- /Chapter07/watershed.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import sys 4 | 5 | 6 | if __name__=='__main__': 7 | # Input image containing all the different shapes 8 | img = cv2.imread(sys.argv[1]) 9 | gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 10 | ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) 11 | 12 | # noise removal 13 | kernel = np.ones((3, 3), np.uint8) 14 | opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=4) 15 | # sure background area 16 | sure_bg = cv2.dilate(opening, kernel, iterations=3) 17 | 18 | # Finding sure foreground area 19 | dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) 20 | ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0) 21 | 22 | # Finding unknown region 23 | sure_fg = np.uint8(sure_fg) 24 | unknown = cv2.subtract(sure_bg, sure_fg) 25 | 26 | # Marker labelling 27 | ret, markers = cv2.connectedComponents(sure_fg) 28 | 29 | # Add one to all labels so that sure background is not 0, but 1 30 | markers = markers+1 31 | 32 | # Now, mark the region of unknown with zero 33 | markers[unknown==255] = 0 34 | markers = cv2.watershed(img, markers) 35 | img[markers==-1] = [255, 255, 255] 36 | cv2.imshow('background', sure_bg) 37 | cv2.imshow('foreground', sure_fg) 38 | cv2.imshow('threshold', thresh) 39 | cv2.imshow('result', img) 40 | cv2.waitKey(0) -------------------------------------------------------------------------------- /Chapter08/background_substraction_GMG.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | # Capture the input frame 5 | def get_frame(cap, scaling_factor=0.5): 6 | ret, frame = cap.read() 7 | 8 | # Resize the frame 9 | frame = cv2.resize(frame, None, fx=scaling_factor, 10 | fy=scaling_factor, interpolation=cv2.INTER_AREA) 11 | 12 | return frame 13 | 14 | if __name__=='__main__': 15 | # Initialize the video capture object 16 | cap = cv2.VideoCapture(1) 17 | 18 | # Create the background subtractor object 19 | bgSubtractor= cv2.bgsegm.createBackgroundSubtractorGMG() 20 | kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, ksize=(3,3)) 21 | 22 | # Iterate until the user presses the ESC key 23 | while True: 24 | frame = get_frame(cap, 0.5) 25 | 26 | # Apply the background subtraction model to the input frame 27 | mask = bgSubtractor.apply(frame) 28 | mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) 29 | 30 | cv2.imshow('Input frame', frame) 31 | cv2.imshow('Moving Objects', mask) 32 | 33 | # Check if the user pressed the ESC key 34 | c = cv2.waitKey(delay=30) 35 | if c == 27: 36 | break 37 | 38 | cap.release() 39 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter08/background_substraction_MOG.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | # Capture the input frame 5 | def get_frame(cap, scaling_factor=0.5): 6 | ret, frame = cap.read() 7 | 8 | # Resize the frame 9 | frame = cv2.resize(frame, None, fx=scaling_factor, 10 | fy=scaling_factor, interpolation=cv2.INTER_AREA) 11 | 12 | return frame 13 | 14 | if __name__=='__main__': 15 | # Initialize the video capture object 16 | cap = cv2.VideoCapture(1) 17 | 18 | # Create the background subtractor object 19 | bgSubtractor = cv2.createBackgroundSubtractorMOG2() 20 | 21 | # This factor controls the learning rate of the algorithm. 22 | # The learning rate refers to the rate at which your model 23 | # will learn about the background. Higher value for 24 | # 'history' indicates a slower learning rate. You 25 | # can play with this parameter to see how it affects 26 | # the output. 27 | history = 100 28 | 29 | # Iterate until the user presses the ESC key 30 | while True: 31 | frame = get_frame(cap, 0.5) 32 | 33 | # Apply the background subtraction model to the input frame 34 | mask = bgSubtractor.apply(frame, learningRate=1.0/history) 35 | 36 | # Convert from grayscale to 3-channel RGB 37 | mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) 38 | 39 | cv2.imshow('Input frame', frame) 40 | cv2.imshow('Moving Objects MOG', mask & frame) 41 | 42 | # Check if the user pressed the ESC key 43 | c = cv2.waitKey(delay=30) 44 | if c == 27: 45 | break 46 | 47 | cap.release() 48 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter08/colorspace_tracking.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | # Capture the input frame from webcam 5 | def get_frame(cap, scaling_factor): 6 | # Capture the frame from video capture object 7 | ret, frame = cap.read() 8 | 9 | # Resize the input frame 10 | frame = cv2.resize(frame, None, fx=scaling_factor, 11 | fy=scaling_factor, interpolation=cv2.INTER_AREA) 12 | 13 | return frame 14 | 15 | if __name__=='__main__': 16 | cap = cv2.VideoCapture(0) 17 | scaling_factor = 0.5 18 | 19 | # Define 'blue' range in HSV colorspace 20 | lower = np.array([60,100,100]) 21 | upper = np.array([180,255,255]) 22 | 23 | while True: 24 | frame = get_frame(cap, scaling_factor) 25 | 26 | # Convert the HSV colorspace 27 | hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 28 | 29 | # Threshold the HSV image to get only blue color 30 | mask = cv2.inRange(hsv_frame, lower, upper) 31 | 32 | # Bitwise-AND mask and original image 33 | res = cv2.bitwise_and(frame, frame, mask=mask) 34 | res = cv2.medianBlur(res, ksize=5) 35 | 36 | cv2.imshow('Original image', frame) 37 | cv2.imshow('Color Detector', res) 38 | 39 | # Check if the user pressed ESC key 40 | c = cv2.waitKey(delay=10) 41 | if c == 27: 42 | break 43 | 44 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter08/detect_movement.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | # Compute the frame difference 4 | def frame_diff(prev_frame, cur_frame, next_frame): 5 | # Absolute difference between current frame and next frame 6 | diff_frames1 = cv2.absdiff(next_frame, cur_frame) 7 | 8 | # Absolute difference between current frame and 9 | # previous frame 10 | diff_frames2 = cv2.absdiff(cur_frame, prev_frame) 11 | 12 | # Return the result of bitwise 'AND' between the 13 | # above two resultant images 14 | return cv2.bitwise_and(diff_frames1, diff_frames2) 15 | 16 | # Capture the frame from webcam 17 | def get_frame(cap, scaling_factor): 18 | # Capture the frame 19 | ret, frame = cap.read() 20 | 21 | # Resize the image 22 | frame = cv2.resize(frame, None, fx=scaling_factor, 23 | fy=scaling_factor, interpolation=cv2.INTER_AREA) 24 | 25 | return frame 26 | 27 | if __name__=='__main__': 28 | cap = cv2.VideoCapture(0) 29 | scaling_factor = 0.5 30 | 31 | cur_frame, prev_frame, next_frame = None, None, None 32 | while True: 33 | frame = get_frame(cap, scaling_factor) 34 | prev_frame = cur_frame 35 | cur_frame = next_frame 36 | # Convert frame to grayscale image 37 | next_frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) 38 | 39 | if prev_frame is not None: 40 | cv2.imshow("Object Movement", frame_diff(prev_frame, cur_frame, next_frame)) 41 | 42 | key = cv2.waitKey(delay=10) 43 | if key == 27: 44 | break 45 | 46 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter08/feature_tracking.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | # Extract area of interest based on the tracking_paths 5 | # In case there is none, entire frame is used 6 | def calculate_region_of_interest(frame, tracking_paths): 7 | mask = np.zeros_like(frame) 8 | mask[:] = 255 9 | for x, y in [np.int32(tp[-1]) for tp in tracking_paths]: 10 | cv2.circle(mask, (x, y), 6, 0, -1) 11 | return mask 12 | 13 | def add_tracking_paths(frame, tracking_paths): 14 | mask = calculate_region_of_interest(frame, tracking_paths) 15 | 16 | # Extract good features to track. You can learn more 17 | # about the parameters here: http://goo.gl/BI2Kml 18 | feature_points = cv2.goodFeaturesToTrack(frame, mask = mask, maxCorners = 500, \ 19 | qualityLevel = 0.3, minDistance = 7, blockSize = 7) 20 | 21 | if feature_points is not None: 22 | for x, y in np.float32(feature_points).reshape(-1, 2): 23 | tracking_paths.append([(x, y)]) 24 | 25 | def compute_feature_points(tracking_paths, prev_img, current_img): 26 | feature_points = [tp[-1] for tp in tracking_paths] 27 | # Vector of 2D points for which the flow needs to be found 28 | feature_points_0 = np.float32(feature_points).reshape(-1, 1, 2) 29 | 30 | feature_points_1, status_1, err_1 = cv2.calcOpticalFlowPyrLK(prev_img, current_img, \ 31 | feature_points_0, None, **tracking_params) 32 | feature_points_0_rev, status_2, err_2 = cv2.calcOpticalFlowPyrLK(current_img, prev_img, \ 33 | feature_points_1, None, **tracking_params) 34 | 35 | # Compute the difference of the feature points 36 | diff_feature_points = abs(feature_points_0-feature_points_0_rev).reshape(-1, 2).max(-1) 37 | 38 | # threshold and keep only the good points 39 | good_points = diff_feature_points < 1 40 | return feature_points_1.reshape(-1, 2), good_points 41 | 42 | def start_tracking(cap, scaling_factor, num_frames_to_track, num_frames_jump, tracking_params): 43 | tracking_paths = [] 44 | frame_index = 0 45 | 46 | # Iterate until the user presses the ESC key 47 | while True: 48 | # read the input frame 49 | ret, frame = cap.read() 50 | 51 | # downsample the input frame 52 | frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA) 53 | 54 | frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 55 | output_img = frame.copy() 56 | 57 | if len(tracking_paths) > 0: 58 | prev_img, current_img = prev_gray, frame_gray 59 | # Compute feature points using optical flow. You can 60 | # refer to the documentation to learn more about the 61 | # parameters here: http://goo.gl/t6P4SE 62 | feature_points, good_points = compute_feature_points(tracking_paths, prev_img, current_img) 63 | 64 | new_tracking_paths = [] 65 | for tp, (x, y), good_points_flag in \ 66 | zip(tracking_paths, feature_points, good_points): 67 | if not good_points_flag: continue 68 | 69 | tp.append((x, y)) 70 | 71 | # Using the queue structure i.e. first in, first out 72 | if len(tp) > num_frames_to_track: del tp[0] 73 | 74 | new_tracking_paths.append(tp) 75 | 76 | # draw green circles on top of the output image 77 | cv2.circle(output_img, (x, y), 3, (0, 255, 0), -1) 78 | 79 | tracking_paths = new_tracking_paths 80 | 81 | # draw green lines on top of the output image 82 | point_paths = [np.int32(tp) for tp in tracking_paths] 83 | cv2.polylines(output_img, point_paths, False, (0, 150, 0)) 84 | 85 | # 'if' condition to skip every 'n'th frame 86 | if not frame_index % num_frames_jump: 87 | add_tracking_paths(frame_gray, tracking_paths) 88 | 89 | frame_index += 1 90 | prev_gray = frame_gray 91 | 92 | cv2.imshow('Optical Flow', output_img) 93 | 94 | # Check if the user pressed the ESC key 95 | c = cv2.waitKey(1) 96 | if c == 27: 97 | break 98 | 99 | if __name__ == '__main__': 100 | # Capture the input frame 101 | cap = cv2.VideoCapture(1) 102 | 103 | # Downsampling factor for the image 104 | scaling_factor = 0.5 105 | 106 | # Number of frames to keep in the buffer when you 107 | # are tracking. If you increase this number, 108 | # feature points will have more "inertia" 109 | num_frames_to_track = 5 110 | 111 | # Skip every 'n' frames. This is just to increase the speed. 112 | num_frames_jump = 2 113 | 114 | # 'winSize' refers to the size of each patch. These patches 115 | # are the smallest blocks on which we operate and track 116 | # the feature points. You can read more about the parameters 117 | # here: http://goo.gl/ulwqLk 118 | tracking_params = dict(winSize = (11, 11), maxLevel = 2, \ 119 | criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) 120 | 121 | start_tracking(cap, scaling_factor, num_frames_to_track, \ 122 | num_frames_jump, tracking_params) 123 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Chapter08/object_tracker.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy as np 4 | 5 | class ObjectTracker(): 6 | def __init__(self): 7 | # Initialize the video capture object 8 | # 0 -> indicates that frame should be captured 9 | # from webcam 10 | self.cap = cv2.VideoCapture(0) 11 | 12 | # Capture the frame from the webcam 13 | ret, self.frame = self.cap.read() 14 | 15 | # Downsampling factor for the input frame 16 | self.scaling_factor = 0.8 17 | self.frame = cv2.resize(self.frame, None, fx=self.scaling_factor, fy=self.scaling_factor, interpolation=cv2.INTER_AREA) 18 | 19 | cv2.namedWindow('Object Tracker') 20 | cv2.setMouseCallback('Object Tracker', self.mouse_event) 21 | 22 | self.selection = None 23 | self.drag_start = None 24 | self.tracking_state = 0 25 | 26 | # Method to track mouse events 27 | def mouse_event(self, event, x, y, flags, param): 28 | x, y = np.int16([x, y]) 29 | 30 | # Detecting the mouse button down event 31 | if event == cv2.EVENT_LBUTTONDOWN: 32 | self.drag_start = (x, y) 33 | self.tracking_state = 0 34 | 35 | if self.drag_start: 36 | if event == cv2.EVENT_MOUSEMOVE: 37 | h, w = self.frame.shape[:2] 38 | xo, yo = self.drag_start 39 | x0, y0 = np.maximum(0, np.minimum([xo, yo], [x, y])) 40 | x1, y1 = np.minimum([w, h], np.maximum([xo, yo], [x, y])) 41 | self.selection = None 42 | 43 | if x1-x0 > 0 and y1-y0 > 0: 44 | self.selection = (x0, y0, x1, y1) 45 | 46 | elif event == cv2.EVENT_LBUTTONUP: 47 | self.drag_start = None 48 | if self.selection is not None: 49 | self.tracking_state = 1 50 | 51 | # Method to start tracking the object 52 | def start_tracking(self): 53 | # Iterate until the user presses the Esc key 54 | while True: 55 | # Capture the frame from webcam 56 | ret, self.frame = self.cap.read() 57 | # Resize the input frame 58 | self.frame = cv2.resize(self.frame, None, fx=self.scaling_factor, fy=self.scaling_factor, interpolation=cv2.INTER_AREA) 59 | 60 | vis = self.frame.copy() 61 | 62 | # Convert to HSV colorspace 63 | hsv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2HSV) 64 | 65 | # Create the mask based on predefined thresholds. 66 | mask = cv2.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.))) 67 | 68 | if self.selection: 69 | x0, y0, x1, y1 = self.selection 70 | self.track_window = (x0, y0, x1-x0, y1-y0) 71 | hsv_roi = hsv[y0:y1, x0:x1] 72 | mask_roi = mask[y0:y1, x0:x1] 73 | 74 | # Compute the histogram 75 | hist = cv2.calcHist( [hsv_roi], [0], mask_roi, [16], [0, 180] ) 76 | 77 | # Normalize and reshape the histogram 78 | cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX); 79 | self.hist = hist.reshape(-1) 80 | 81 | vis_roi = vis[y0:y1, x0:x1] 82 | cv2.bitwise_not(vis_roi, vis_roi) 83 | vis[mask == 0] = 0 84 | 85 | if self.tracking_state == 1: 86 | print('tracking') 87 | self.selection = None 88 | 89 | # Compute the histogram back projection 90 | prob = cv2.calcBackProject([hsv], [0], self.hist, [0, 180], 1) 91 | 92 | prob &= mask 93 | term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 ) 94 | 95 | # Apply CAMShift on 'prob' 96 | track_box, self.track_window = cv2.CamShift(prob, self.track_window, term_crit) 97 | 98 | # Draw an ellipse around the object 99 | cv2.ellipse(vis, track_box, (0, 255, 0), 2) 100 | 101 | cv2.imshow('Object Tracker', vis) 102 | 103 | c = cv2.waitKey(delay=5) 104 | if c == 27: 105 | break 106 | 107 | cv2.destroyAllWindows() 108 | 109 | if __name__ == '__main__': 110 | ObjectTracker().start_tracking() -------------------------------------------------------------------------------- /Chapter09/classify_data.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | import _pickle as pickle 5 | 6 | import cv2 7 | import numpy as np 8 | 9 | import create_features as cf 10 | from training import ClassifierTrainer 11 | 12 | # Classifying an image 13 | class ImageClassifier(object): 14 | def __init__(self, svm_file, codebook_file): 15 | # Load the SVM classifier 16 | with open(svm_file, 'rb') as f: 17 | self.svm = pickle.load(f) 18 | 19 | # Load the codebook 20 | with open(codebook_file, 'rb') as f: 21 | self.kmeans, self.centroids = pickle.load(f) 22 | 23 | # Method to get the output image tag 24 | def getImageTag(self, img): 25 | # Resize the input image 26 | img = cf.resize_to_size(img) 27 | 28 | # Extract the feature vector 29 | feature_vector = cf.FeatureExtractor().get_feature_vector(img, self.kmeans, self.centroids) 30 | 31 | # Classify the feature vector and get the output tag 32 | image_tag = self.svm.classify(feature_vector) 33 | 34 | return image_tag 35 | 36 | 37 | def build_arg_parser(): 38 | parser = argparse.ArgumentParser(description='Extracts features from each line and classifies the data') 39 | parser.add_argument("--input-image", dest="input_image", required=True,\ 40 | help="Input image to be classified") 41 | parser.add_argument("--svm-file", dest="svm_file", required=True,\ 42 | help="File containing the trained SVM model") 43 | parser.add_argument("--codebook-file", dest="codebook_file", required=True,\ 44 | help="File containing the codebook") 45 | return parser 46 | 47 | if __name__=='__main__': 48 | args = build_arg_parser().parse_args() 49 | svm_file = args.svm_file 50 | codebook_file = args.codebook_file 51 | input_image = cv2.imread(args.input_image) 52 | 53 | tag = ImageClassifier(svm_file, codebook_file).getImageTag(input_image) 54 | print("Output class:", tag) -------------------------------------------------------------------------------- /Chapter09/create_features.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | import _pickle as pickle 5 | import json 6 | 7 | import cv2 8 | import numpy as np 9 | from sklearn.cluster import KMeans 10 | 11 | class DenseDetector(): 12 | def __init__(self, step_size=20, feature_scale=20, img_bound=20): 13 | # Create a dense feature detector 14 | self.initXyStep = step_size 15 | self.initFeatureScale = feature_scale 16 | self.initImgBound = img_bound 17 | 18 | def detect(self, img): 19 | keypoints = [] 20 | rows, cols = img.shape[:2] 21 | for x in range(self.initImgBound, rows, self.initFeatureScale): 22 | for y in range(self.initImgBound, cols, self.initFeatureScale): 23 | keypoints.append(cv2.KeyPoint(float(x), float(y), self.initXyStep)) 24 | return keypoints 25 | 26 | class SIFTExtractor(): 27 | def __init__(self): 28 | self.extractor = cv2.xfeatures2d.SIFT_create() 29 | 30 | def compute(self, image, kps): 31 | if image is None: 32 | print("Not a valid image") 33 | raise TypeError 34 | 35 | gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 36 | kps, des = self.extractor.detectAndCompute(gray_image, None) 37 | return kps, des 38 | 39 | # Vector quantization 40 | class Quantizer(object): 41 | def __init__(self, num_clusters=32): 42 | self.num_dims = 128 43 | self.extractor = SIFTExtractor() 44 | self.num_clusters = num_clusters 45 | self.num_retries = 10 46 | 47 | def quantize(self, datapoints): 48 | # Create KMeans object 49 | kmeans = KMeans(self.num_clusters, 50 | n_init=max(self.num_retries, 1), 51 | max_iter=10, tol=1.0) 52 | 53 | # Run KMeans on the datapoints 54 | res = kmeans.fit(datapoints) 55 | 56 | # Extract the centroids of those clusters 57 | centroids = res.cluster_centers_ 58 | 59 | return kmeans, centroids 60 | 61 | def normalize(self, input_data): 62 | sum_input = np.sum(input_data) 63 | if sum_input > 0: 64 | return input_data / sum_input 65 | else: 66 | return input_data 67 | 68 | # Extract feature vector from the image 69 | def get_feature_vector(self, img, kmeans, centroids): 70 | kps = DenseDetector().detect(img) 71 | kps, fvs = self.extractor.compute(img, kps) 72 | labels = kmeans.predict(fvs) 73 | fv = np.zeros(self.num_clusters) 74 | 75 | for i, item in enumerate(fvs): 76 | fv[labels[i]] += 1 77 | 78 | fv_image = np.reshape(fv, ((1, fv.shape[0]))) 79 | return self.normalize(fv_image) 80 | 81 | 82 | class FeatureExtractor(object): 83 | def extract_image_features(self, img): 84 | # Dense feature detector 85 | kps = DenseDetector().detect(img) 86 | 87 | # SIFT feature extractor 88 | kps, fvs = SIFTExtractor().compute(img, kps) 89 | 90 | return fvs 91 | 92 | # Extract the centroids from the feature points 93 | def get_centroids(self, input_map, num_samples_to_fit=10): 94 | kps_all = [] 95 | 96 | count = 0 97 | cur_label = '' 98 | for item in input_map: 99 | if count >= num_samples_to_fit: 100 | if cur_label != item['label']: 101 | count = 0 102 | else: 103 | continue 104 | 105 | count += 1 106 | 107 | if count == num_samples_to_fit: 108 | print("Built centroids for", item['label']) 109 | 110 | cur_label = item['label'] 111 | img = cv2.imread(item['image']) 112 | img = resize_to_size(img, 150) 113 | 114 | num_dims = 128 115 | fvs = self.extract_image_features(img) 116 | kps_all.extend(fvs) 117 | 118 | kmeans, centroids = Quantizer().quantize(kps_all) 119 | return kmeans, centroids 120 | 121 | def get_feature_vector(self, img, kmeans, centroids): 122 | return Quantizer().get_feature_vector(img, kmeans, centroids) 123 | 124 | 125 | def build_arg_parser(): 126 | parser = argparse.ArgumentParser(description='Creates features for given images') 127 | parser.add_argument("--samples", dest="cls", nargs="+", action="append", required=True,\ 128 | help="Folders containing the training images.\nThe first element needs to be the class label.") 129 | parser.add_argument("--codebook-file", dest='codebook_file', required=True, 130 | help="Base file name to store the codebook") 131 | parser.add_argument("--feature-map-file", dest='feature_map_file', required=True,\ 132 | help="Base file name to store the feature map") 133 | 134 | return parser 135 | 136 | # Loading the images from the input folder 137 | def load_input_map(label, input_folder): 138 | combined_data = [] 139 | 140 | if not os.path.isdir(input_folder): 141 | raise IOError("The folder " + input_folder + " doesn't exist") 142 | 143 | # Parse the input folder and assign the labels 144 | for root, dirs, files in os.walk(input_folder): 145 | for filename in (x for x in files if x.endswith('.jpg')): 146 | combined_data.append({'label': label, 'image': 147 | os.path.join(root, filename)}) 148 | 149 | return combined_data 150 | 151 | def extract_feature_map(input_map, kmeans, centroids): 152 | feature_map = [] 153 | 154 | for item in input_map: 155 | temp_dict = {} 156 | temp_dict['label'] = item['label'] 157 | 158 | print("Extracting features for", item['image']) 159 | img = cv2.imread(item['image']) 160 | img = resize_to_size(img, 150) 161 | 162 | temp_dict['feature_vector'] = FeatureExtractor().get_feature_vector(img, kmeans, centroids) 163 | 164 | if temp_dict['feature_vector'] is not None: 165 | feature_map.append(temp_dict) 166 | 167 | return feature_map 168 | 169 | # Resize the shorter dimension to 'new_size' 170 | # while maintaining the aspect ratio 171 | def resize_to_size(input_image, new_size=150): 172 | h, w = input_image.shape[0], input_image.shape[1] 173 | ds_factor = new_size / float(h) 174 | 175 | if w < h: 176 | ds_factor = new_size / float(w) 177 | 178 | new_size = (int(w * ds_factor), int(h * ds_factor)) 179 | return cv2.resize(input_image, new_size) 180 | 181 | if __name__=='__main__': 182 | args = build_arg_parser().parse_args() 183 | 184 | input_map = [] 185 | for cls in args.cls: 186 | assert len(cls) >= 2, "Format for classes is `