<jupyter_start><jupyter_text>1. Contours  1.1 Finding and Drawing Contours<jupyter_code>image = cv2.imread('../img/shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,230,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

clone = image.copy()
clone = cv2.drawContours(clone, contours, 10, (0,0,255), 1)
show_image(np.flip(clone, axis=2))
clone = image.copy()
cnt = contours[3]
clone = cv2.drawContours(clone.copy(), [cnt], 0, (0,255,0), 10)
show_image(np.flip(clone, axis=2))<jupyter_output><empty_output><jupyter_text>1.2 Basic Contour Features  1.2.1 Contour Area and Perimeter<jupyter_code>image = cv2.imread('../img/basic_shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,10,255,0)
contours = cv2.findContours(thresh, 1, 2)[0]

cnt = contours[0]
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

# loop over the contours again
for (i, c) in enumerate(contours):
    # compute the area and the perimeter of the contour
    area = cv2.contourArea(c)
    perimeter = cv2.arcLength(c, True)
    clone = image.copy()
    print("Contour #{} -- area: {:.2f}, perimeter: {:.2f}".format(i + 1, area, perimeter))
 
    # draw the contour on the image
    cv2.drawContours(clone, [c], -1, (0, 255, 0), 2)
 
    # compute the center of the contour and draw the contour number
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    cv2.putText(clone, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,
        1.25, (255, 255, 255), 4)
    
    show_image(clone)<jupyter_output><empty_output><jupyter_text>1.2.4 Contour Bounding Boxes<jupyter_code>image = cv2.imread('../img/basic_shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,10,255,0)
contours = cv2.findContours(thresh, 1, 2)[0]

# loop over the contours again
for (i, c) in enumerate(contours):
    clone = image.copy()
    print("Contour #{}".format(i + 1))
 
    # draw the contour on the image
    cv2.drawContours(clone, [c], -1, (0, 255, 0), 2)
 
    # compute the center of the contour and draw the contour number
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    cv2.putText(clone, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,
        1.25, (255, 255, 255), 4)
    
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(clone,(x,y),(x+w,y+h),(255,255,255),4)
    
    show_image(clone)<jupyter_output><empty_output><jupyter_text>1.2.5 Contour Minimum Enclosing Circles<jupyter_code>image = cv2.imread('../img/basic_shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,10,255,0)
contours = cv2.findContours(thresh, 1, 2)[0]

# loop over the contours again
for (i, c) in enumerate(contours):
    clone = image.copy()
    print("Contour #{}".format(i + 1))
 
    # draw the contour on the image
    cv2.drawContours(clone, [c], -1, (0, 255, 0), 2)
 
    # compute the center of the contour and draw the contour number
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    cv2.putText(clone, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,
        1.25, (255, 255, 255), 4)
    
    (x,y),radius = cv2.minEnclosingCircle(c)
    center = (int(x),int(y))
    radius = int(radius)
    clone = cv2.circle(clone,center,radius,(255,255,255),4)
    
    show_image(clone)<jupyter_output><empty_output><jupyter_text>1.2.6 Fitting an Ellipse<jupyter_code>image = cv2.imread('../img/basic_shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,10,255,0)
contours = cv2.findContours(thresh, 1, 2)[0]

ellipse = cv2.fitEllipse(contours[0])
cv2.ellipse(image,ellipse,(255,255,255),4)

show_image(image)<jupyter_output><empty_output><jupyter_text>EXERCISE: Fit a circle, bounding box and ellipse to objects of an image. What are their properties?<jupyter_code>image = np.flip(cv2.imread('../img/shapes.png'), axis =2 )
show_image(image)<jupyter_output><empty_output><jupyter_text>1.3 Advanced Contour Features  1.3.1 Aspect Ratio<jupyter_code>image = cv2.imread('../img/basic_shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,10,255,0)
contours = cv2.findContours(thresh, 1, 2)[0]

# loop over the contours again
for (i, c) in enumerate(contours):
    clone = image.copy()
    
    # compute the area and the aspect ratio of the contour
    x,y,w,h = cv2.boundingRect(c)
    aspect_ratio = float(w)/h
    print("Contour #{} -- aspect Ratio: {:.2f}".format(i + 1, aspect_ratio))
 
    # draw the contour on the image
    cv2.drawContours(clone, [c], -1, (0, 255, 0), 2)
 
    # compute the center of the contour and draw the contour number
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    cv2.putText(clone, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,
        1.25, (255, 255, 255), 4)
    
    show_image(clone)<jupyter_output><empty_output><jupyter_text>1.3.2 Extent<jupyter_code>image = cv2.imread('../img/basic_shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,10,255,0)
contours = cv2.findContours(thresh, 1, 2)[0]

# loop over the contours again
for (i, c) in enumerate(contours):
    clone = image.copy()
    
    # compute the area and the aspect ratio of the contour
    area = cv2.contourArea(c)
    x,y,w,h = cv2.boundingRect(c)
    rect_area = w*h
    extent = float(area)/rect_area
    print("Contour #{} -- area: {:.2f}, Rectangular area: {:.2f}, extent: {:.2f}".format(i + 1, area, rect_area, extent))
 
    # draw the contour on the image
    cv2.drawContours(clone, [c], -1, (0, 255, 0), 2)
 
    # compute the center of the contour and draw the contour number
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    cv2.putText(clone, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,
        1.25, (255, 255, 255), 4)
    
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(clone,(x,y),(x+w,y+h),(255,255,255),4)
    
    show_image(clone)<jupyter_output><empty_output><jupyter_text>1.3.3 Convexity<jupyter_code>image = cv2.imread('../img/basic_shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,10,255,0)
contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]

# loop over the contours again
for (i, c) in enumerate(contours):
    clone = image.copy()
    
    # Check convexity
    is_convex = cv2.isContourConvex(c)
    print("Contour #{} -- Convex: {}".format(i + 1, is_convex))
 
    # draw the contour on the image
    cv2.drawContours(clone, [c], -1, (0, 255, 0), 4)
 
    # compute the center of the contour and draw the contour number
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    cv2.putText(clone, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,
        1.25, (255, 255, 255), 2)
    
    show_image(clone)<jupyter_output><empty_output><jupyter_text>1.3.4 Solidity<jupyter_code># load the tic-tac-toe image and convert it to grayscale
image = cv2.imread("../img/tetris_blocks.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1]
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]

# loop over the contours again
for (i, c) in enumerate(contours):
    clone = image.copy()
    
    area = cv2.contourArea(c)
    hull = cv2.convexHull(c)
    hull_area = cv2.contourArea(hull)
    solidity = float(area)/hull_area
    
    # Check convexity
    print(f"Contour #{i+1} -- area: {area}, Hull Area: {hull_area}, Solidity: {solidity}")
 
    # draw the contour and hull on the image
    cv2.drawContours(clone, [hull], -1, 255, 10)
    cv2.drawContours(clone, [c], -1, (0, 255, 0), 4)
 
    # compute the center of the contour and draw the contour number
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    cv2.putText(clone, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,
        1.25, (0, 0, 0), 2)
    
    show_image(clone)<jupyter_output><empty_output><jupyter_text>2. Identifying Shapes in Images using Contours<jupyter_code># load the Tetris block image, convert it to grayscale, and threshold
# the image
image = cv2.imread("../img/tetris_blocks.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1]
 
# show the original and thresholded images
cv2.imshow("Original", image)
cv2.imshow("Thresh", thresh)
 
# find external contours in the thresholded image and allocate memory
# for the convex hull image
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
hullImage = np.zeros(gray.shape[:2], dtype="uint8")

# loop over the contours
for (i, c) in enumerate(cnts):
    # compute the area of the contour along with the bounding box
    # to compute the aspect ratio
    area = cv2.contourArea(c)
    (x, y, w, h) = cv2.boundingRect(c)

    # compute the aspect ratio of the contour, which is simply the width
    # divided by the height of the bounding box
    aspectRatio = w / float(h)

    # use the area of the contour and the bounding box area to compute
    # the extent
    extent = area / float(w * h)

    # compute the convex hull of the contour, then use the area of the
    # original contour and the area of the convex hull to compute the
    # solidity
    hull = cv2.convexHull(c)
    hullArea = cv2.contourArea(hull)
    solidity = area / float(hullArea)

    # visualize the original contours and the convex hull and initialize
    # the name of the shape
    cv2.drawContours(hullImage, [hull], -1, 255, -1)
    cv2.drawContours(image, [c], -1, (240, 0, 159), 3)
    shape = ""
    
    # if the aspect ratio is approximately one, then the shape is a square
    if aspectRatio >= 0.98 and aspectRatio <= 1.02:
        shape = "SQUARE"

    # if the width is 3x longer than the height, then we have a rectangle
    elif aspectRatio >= 3.0:
        shape = "RECTANGLE"

    # if the extent is sufficiently small, then we have a L-piece
    elif extent < 0.65:
        shape = "L-PIECE"

    # if the solidity is sufficiently large enough, then we have a Z-piece
    elif solidity > 0.80:
        shape = "Z-PIECE"

    # draw the shape name on the image
    cv2.putText(image, shape, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
        (240, 0, 159), 2)

    # show the contour properties
    print("Contour #{} -- aspect_ratio={:.2f}, extent={:.2f}, solidity={:.2f}"
        .format(i + 1, aspectRatio, extent, solidity))

# show the output images
show_image(hullImage)
show_image(image)<jupyter_output><empty_output><jupyter_text>EXERCISE: Use contour properties to identify shape of objects in the following image<jupyter_code>image = np.flip(cv2.imread("../img/shapes.png"), axis = 2)
show_image(image)
# TODO: Your code below<jupyter_output><empty_output><jupyter_text>1.4 Contour Retrieval Modes<jupyter_code>image = cv2.imread('../img/basic_shapes.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,10,255,0)

contour_retrieval_modes = [cv2.RETR_LIST, cv2.RETR_EXTERNAL, cv2.RETR_CCOMP, cv2.RETR_TREE]
names = ['RETR_LIST', 'RETR_EXTERNAL', 'RETR_CCOMP', 'RETR_TREE']

for rm, name in zip(contour_retrieval_modes, names):
    img = gray.copy()
    contours = cv2.findContours(thresh,rm,cv2.CHAIN_APPROX_SIMPLE)[0]
    
    for (i, c) in enumerate(contours):
        (x, y, w, h) = cv2.boundingRect(c)
        
        M = cv2.moments(c)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
        
        cv2.drawContours(img, [c], -1, (255, 255, 255), 4)
        
        
        # draw the shape name on the image
        cv2.putText(img, str(i+1), (cX, cY), cv2.FONT_HERSHEY_SIMPLEX, 1, (240, 0, 159), 2)
    
    print(name)
    show_image(img)<jupyter_output><empty_output><jupyter_text>PROJECT: Identify Xs and Os in the tic tac toe board<jupyter_code>image = np.flip(cv2.imread("../img/tictactoe.png"), axis = 2)
show_image(image)
# %load ../solutions/tic-tac-toe.py
# load the tic-tac-toe image and convert it to grayscale
image = cv2.imread("../img/tictactoe.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
# find all contours on the tic-tac-toe board
cnts = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
 
# loop over the contours
for (i, c) in enumerate(cnts):
    # compute the area of the contour along with the bounding box
    # to compute the aspect ratio
    area = cv2.contourArea(c)
    (x, y, w, h) = cv2.boundingRect(c)

    # compute the convex hull of the contour, then use the area of the
    # original contour and the area of the convex hull to compute the
    # solidity
    hull = cv2.convexHull(c)
    hullArea = cv2.contourArea(hull)
    solidity = area / float(hullArea)

    # initialize the character text
    char = "?"

    # if the solidity is high, then we are examining an `O`
    if solidity > 0.9:
        char = "O"

    # otherwise, if the solidity it still reasonabably high, we
    # are examining an `X`
    elif solidity > 0.5:
        char = "X"

    # if the character is not unknown, draw it
    if char != "?":
        cv2.drawContours(image, [c], -1, (0, 255, 0), 3)
        cv2.putText(image, char, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.25,
            (0, 255, 0), 4)

    # show the contour properties
    print("{} (Contour #{}) -- solidity={:.2f}".format(char, i + 1, solidity))
    
show_image(image)<jupyter_output><empty_output><jupyter_text>PROJECT: Use contour properties to identify licence plate in images<jupyter_code>image = np.flip(cv2.imread("../img/licence_plate_raw.png"), axis = 2)
show_image(image)
# TODO: Your code below<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1501212380544858, 'fraction_numerical': 0.04935101982598773, 'mean_word_length': 3.6665557404326123, 'pattern_counts': {'":': 1, '<': 63, '<?xml version=': 0, '>': 66, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '206655', 'license': 'MIT', 'n_tokens_mistral': 6002, 'n_tokens_neox': 5464, 'n_words': 1307, 'path': 'notebooks/Lesson 5 - Contours.ipynb', 'repo_name': 'beginners-machine-learning-london/computer_vision_basics', 'size': '14022'}