#!/usr/bin/env python# encoding: utf-8import argparseimport cv2import imutils# construct the argument parser and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--image", required=False, default='tetris_blocks.png', help="path to input image")args = vars(ap.parse_args())# load the input image (whose path was supplied via command line# argument) and display the image to our screenimage = cv2.imread(args["image"])cv2.imshow("Image", image)cv2.waitKey(0)# convert the image to grayscalegray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)cv2.imshow("Gray", gray)cv2.waitKey(0)# applying edge detection we can find the outlines of objects in# imagesedged = cv2.Canny(gray, 30, 150)cv2.imshow("Edged", edged)cv2.waitKey(0)# threshold the image by setting all pixel values less than 225# to 255 (white; foreground) and all pixel values >= 225 to 255# (black; background), thereby segmenting the imagethresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1]cv2.imshow("Thresh", thresh)cv2.waitKey(0)# a typical operation we may want to apply is to take our mask and# apply a bitwise AND to our input image, keeping only the masked# regionsmask = thresh.copy()output = cv2.bitwise_and(image, image, mask=mask)cv2.imshow("Output", output)cv2.waitKey(0)# we apply erosions to reduce the size of foreground objectsmask = thresh.copy()mask = cv2.erode(mask, None, iterations=5)cv2.imshow("Eroded", mask)cv2.waitKey(0)# similarly, dilations can increase the size of the ground objectsmask = thresh.copy()mask = cv2.dilate(mask, None, iterations=5)cv2.imshow("Dilated", mask)cv2.waitKey(0)# find contours (i.e., outlines) of the foreground objects in the# thresholded imagecnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)output = image.copy()# loop over the contoursfor c in cnts:# draw each contour on the output image with a 3px thick purple# outline, then display the output contours one at a timecv2.drawContours(output, [c], -1, (240, 0, 159), 3)cv2.imshow("Contours", output)cv2.waitKey(0)pass# draw the total number of contours found in purpletext = "I found {} objects!".format(len(cnts))cv2.putText(output, text, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (240, 0, 159), 2)cv2.imshow("Contours", output)cv2.waitKey(0)


ROI
Extracting “regions of interest” (ROIs) is an important skill for image processing.
Processing
Take note that drawing operations on images are performed in-place. Therefore at the beginning of each code block, we make a copy of the original image storing the copy

Canny
parameters to the cv2.Canny function:
- img : The gray image.
- minVal : A minimum threshold, in our case 30 .
- maxVal : The maximum threshold which is 150 in our example.
- aperture_size : The Sobel kernel size. By default this value is 3.
Thresholding
# threshold the image by setting all pixel values less than 225# to 255 (white; foreground) and all pixel values >= 225 to 255# (black; background), thereby segmenting the imagethresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1]cv2.imshow("Thresh", thresh)cv2.waitKey(0)
- Grabbing all pixels in the
grayimage greater than 225 and setting them to 0 (black) which corresponds to the background of the image. - Setting pixel vales less than 225 to 255 (white) which corresponds to the foreground of the image.
Contours
Erosions and dilations
Erosions and dilations are typically used to reduce noise in binary images (a side effect of thresholding).
