DEV Community

Cover image for How to remove an object from an image with Python
Stokry
Stokry

Posted on

How to remove an object from an image with Python

Today I want to show you a sweet algorithm with which you can remove objects from the picture. For example, if we have thousands of images where we have some objects that we want to delete, this algorithm can help us complete this task.

We will be using modified Template Matching approach.
We will load the template, convert to grayscale, perform canny edge detection, after that we do load the original image, convert to grayscale
Continuously rescale the image, apply template matching using edges, and keep track of the correlation coefficient (higher value means better match)
Find coordinates of best-fit bounding box then erase unwanted ROI
We'll use the cv2 module and NumPy. You can read about them on these URLs.

We'll use the cv2 module and NumPy. You can read about them on these URLs, CV2, and Numpy.

Let's start coding
First we will import a module

import cv2
import numpy as np
Enter fullscreen mode Exit fullscreen mode

After that we do resize a image and maintain aspect ratio

def  maintain_aspect_ratio_resize(image,  width=None,  height=None,  inter=cv2.INTER_AREA):
Enter fullscreen mode Exit fullscreen mode

then we grab the image size and initialize dimensions

dim =  None
(h, w)  = image.shape[:2]
Enter fullscreen mode Exit fullscreen mode

then we return original image if no need to resize:

if width is  None  and height is  None:
    return image
Enter fullscreen mode Exit fullscreen mode

We are resizing height if width is none

if width is  None:
    r = height /  float(h)
    dim =  (int(w * r), height)
Enter fullscreen mode Exit fullscreen mode

We are resizing width if height is none

else:
    r = width /  float(w)
    dim =  (width,  int(h * r))
Enter fullscreen mode Exit fullscreen mode

Return the resized image

return cv2.resize(image, dim,  interpolation=inter)
Enter fullscreen mode Exit fullscreen mode

Load template, convert to grayscale, perform canny edge detection

template = cv2.imread('template.png')
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template,  50,  200)
(tH, tW)  = template.shape[:2]
cv2.imshow("template", template)
Enter fullscreen mode Exit fullscreen mode

Load original image, convert to grayscale

original_image = cv2.imread('test.png')
final = original_image.copy()
gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
found =  None
Enter fullscreen mode Exit fullscreen mode

Dynamically rescale image for better template matching

for scale in np.linspace(0.2,  1.0,  20)[::-1]:
      resized = maintain_aspect_ratio_resize(gray,  width=int(gray.shape[1]  * scale))
      r = gray.shape[1]  /  float(resized.shape[1])

      if resized.shape[0]  < tH or resized.shape[1]  < tW:
          break

      canny = cv2.Canny(resized,  50,  200)
      detected = cv2.matchTemplate(canny, template, cv2.TM_CCOEFF)
      (_, max_val, _, max_loc)  = cv2.minMaxLoc(detected)
      if found is  None  or max_val > found[0]:
         found =  (max_val, max_loc, r)
Enter fullscreen mode Exit fullscreen mode

Compute coordinates of bounding box

(_, max_loc, r)  = found
(start_x, start_y)  =  (int(max_loc[0]  * r),  int(max_loc[1]  * r))
(end_x, end_y)  =  (int((max_loc[0]  + tW)  * r),  int((max_loc[1]  + tH)  * r))
Enter fullscreen mode Exit fullscreen mode

Draw bounding box on ROI to remove

cv2.rectangle(original_image,  (start_x, start_y),  (end_x, end_y),  (0,255,0),  2)
cv2.imshow('detected', original_image)
Enter fullscreen mode Exit fullscreen mode

Erase unwanted ROI (Fill ROI with white)

cv2.rectangle(final,  (start_x, start_y),  (end_x, end_y),  (255,255,255),  -1)
cv2.imwrite('final.png', final)
cv2.waitKey(0)
Enter fullscreen mode Exit fullscreen mode

Original image:

enter image description here

When we run the script, we get this result

enter image description here

Whole code:

import cv2
import numpy as np

def  maintain_aspect_ratio_resize(image,  width=None,  height=None,  inter=cv2.INTER_AREA):
     dim =  None
     (h, w)  = image.shape[:2]
     if width is  None  and height is  None:
        return image

     if width is  None:
        r = height /  float(h)
        dim =  (int(w * r), height)
      else:
          r = width /  float(w)
          dim =  (width,  int(h * r))

       return cv2.resize(image, dim,  interpolation=inter)


template = cv2.imread('template.png')
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template,  50,  200)
(tH, tW)  = template.shape[:2]
cv2.imshow("template", template)

original_image = cv2.imread('test.png')
final = original_image.copy()
gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
found =  None

for scale in np.linspace(0.2,  1.0,  20)[::-1]:
     resized = maintain_aspect_ratio_resize(gray,  width=int(gray.shape[1]  * scale))
     r = gray.shape[1]  /  float(resized.shape[1])

     if resized.shape[0]  < tH or resized.shape[1]  < tW:
        break
     canny = cv2.Canny(resized,  50,  200)
     detected = cv2.matchTemplate(canny, template, cv2.TM_CCOEFF)
     (_, max_val, _, max_loc)  = cv2.minMaxLoc(detected)

     if found is  None  or max_val > found[0]:
        found =  (max_val, max_loc, r)

(_, max_loc, r)  = found
(start_x, start_y)  =  (int(max_loc[0]  * r),  int(max_loc[1]  * r))
(end_x, end_y)  =  (int((max_loc[0]  + tW)  * r),  int((max_loc[1]  + tH)  * r))


cv2.rectangle(original_image,  (start_x, start_y),  (end_x, end_y),  (0,255,0),  2)
cv2.imshow('detected', original_image)

cv2.rectangle(final,  (start_x, start_y),  (end_x, end_y),  (255,255,255),  -1)
cv2.imwrite('final.png', final)
cv2.waitKey(0)
Enter fullscreen mode Exit fullscreen mode

Thank you all

Top comments (11)

Collapse
 
bala profile image
Balamurugan

Can you please explain...How can we remove duplicate objects in a single image?

Collapse
 
stokry profile image
Stokry
Collapse
 
bala profile image
Balamurugan

Also, In this example, our goal is to remove the circles/ellipses from the image. But my requirement is to Remove the duplicate objects from the image using template matching techniques.

Thread Thread
 
stokry profile image
Stokry

This is a nice tutorial: towardsdatascience.com/object-dete...

Collapse
 
bala profile image
Balamurugan

Thanks for your reply, But I need the different requirements. This link finds the duplicate by contours. but I need to find the multiple objects using the template matching techniques

Thread Thread
 
bala profile image
Balamurugan

Already, I derived the code, the problem is..I have one template to find the matching object in that image..I have totally 5 duplicates but my system shows 6 duplicates one is wrong identifying..Am trying to fix it. I have your support it will better

Collapse
 
bala profile image
Balamurugan

Hi,Nice Explanation

Collapse
 
stokry profile image
Stokry

Thanks!

Collapse
 
jingxue profile image
Jing Xue

Now I know how they got rid of Daenerys' Starbucks cup!

Collapse
 
bala profile image
Balamurugan

Can you please give some idea to remove all the matching objects from the original image using python and OpenCV method or Template matching techniques?

Collapse
 
stokry profile image
Stokry

I'm just finishing up a similar article, and I'm about to publish it on the dev.to.