The artistic shape detection algorithm

Today I learned one simple shape detection algorithm. In contrast image, it tries to find how many corners on some shapes are. When there is three, then it is a triangle and so on. And draws coloured contour around it. In a controlled environment, it works mostly as supposed. When you released it to the real wild world it gives quite artistic results.

#!/usr/bin/env python3

'''
Shape detection from images.
Tauno Erik
13.05.2021
'''

import cv2 as cv
import os

# Colors (BGR)
RED = (0,0,255)
GREEN = (0,255,0)
BLUE = (255,0,0)
YELLOW = (0,255,255)
CYAN = (255,255,0)
MAGENTA = (255,0,255)
ORANGE = (0,140,255)
PINK = (147,20,255)
PURPLE = (128,0,128)
GOLDEN = (32,165,218)
BROWN = (42,42,165)

def full_path(filename):
  ''' Returns full path to file. '''
  folder = os.path.dirname(__file__) # File location
  full_path = os.path.join(folder, filename)
  return full_path

def shape_detection(file):
  img = cv.imread(file)
  gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
  ret, thresh = cv.threshold(gray, 50, 255, 1)
  contours, h = cv.findContours(thresh, 1, 2)

  img_hall = cv.cvtColor(gray, cv.COLOR_GRAY2BGR)

  for cnt in contours:
    approx = cv.approxPolyDP(cnt, 0.01*cv.arcLength(cnt, True), True)  # Returns array
    print("Shape with {} pints".format(len(approx)))
    n = len(approx)

    if n is 15 or n is 16:
      cv.drawContours(img_hall, [cnt], 0, YELLOW, 5)
    elif n is 12:
      cv.drawContours(img_hall, [cnt], 0, BROWN, 5)
    elif n is 11:
      cv.drawContours(img_hall, [cnt], 0, GOLDEN, 5)
    elif n is 10:
      cv.drawContours(img_hall, [cnt], 0, PURPLE, 5)
    elif n is 9:
      cv.drawContours(img_hall, [cnt], 0, PINK, 5)
    elif n is 8:
      cv.drawContours(img_hall, [cnt], 0, CYAN, 5)
    elif n is 7:
      cv.drawContours(img_hall, [cnt], 0, ORANGE, 5)
    elif n is 6:
      cv.drawContours(img_hall, [cnt], 0, CYAN, 5)
    elif n is 5:
      cv.drawContours(img_hall, [cnt], 0, RED, 5)
    elif n is 4:
      cv.drawContours(img_hall, [cnt], 0, GREEN, 5)
    elif n is 3:
      cv.drawContours(img_hall, [cnt], 0, BLUE, 5)

  cv.imshow('Shaps', img_hall)
  cv.waitKey(0)


if __name__ == "__main__":
  print('Shape detection!')
  print('To close window press: q')

  file = full_path('images/kujundid.jpg')
  shape_detection(file)

3 Comments

  1. That’d probably be quite helpful to new artists trying to spot the big shapes (and negative space) in a subject they’re trying to paint.

    Cool effect in the video too. 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.