-1

I am using this code to remove this yellow stamp from an image :

import cv2
import numpy as np

# read image
img = cv2.imread('input.jpg')

# threshold on yellow
lower = (0, 200, 200)
upper = (100, 255, 255)
thresh = cv2.inRange(img, lower, upper)

# apply dilate morphology
kernel = np.ones((9, 9), np.uint8)
mask = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, kernel)

# get largest contour
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(big_contour)

# draw filled white contour on input
result = img.copy()
cv2.drawContours(result, [big_contour], 0, (255, 255, 255), -1)


cv2.imwrite('yellow_removed.png', result)

# show the images
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

I get the following error:

big_contour = max(contours, key=cv2.contourArea) ValueError: max() arg is an empty sequence

Obviously, it is not detecting any contours, and the contours array is empty, but I could not figure out why that is or how to fix it. Help is appreciated!

Mar1941
  • 91
  • 1
  • 10

3 Answers3

1

Check your lower thresholds. It worked for me for both images when I changed the lower threshold to lower = (0, 120, 120).

shounak shastri
  • 113
  • 1
  • 2
  • 8
1

The thresholds is the reason due to the second image being darker. Lowering these thresholds captures more of the yellow area, but will still leave some holes when drawing the contour.

lower = (0, 130, 130)

holes left in image

You can fix this by drawing the bounding rectangle instead.

cv2.rectangle(result,(x,y),(x+w,y+h),(255,255,255),-1)

enter image description here

DNy
  • 742
  • 1
  • 6
  • 15
1

Using HSV color space is great for figuring out a particular shade/tone of color. When you have dominant colors to isolate, you can opt for the LAB color space. I have explained as to why this is better in this answer.

Code:

img = cv2.imread('bill.jpg')
# create another copy for the result
img2 = img.copy()

# convert to LAB space and store b-channel
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
b_channel = lab[:,:,-1]

enter image description here

Notice how bright the yellow region is above.

# Perform Otsu threshold
th = cv2.threshold(b_channel, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

enter image description here

# Find the contour with largest area
contours, hierarchy = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
c = max(contours, key = cv2.contourArea)

# draw the contour on plain black image of same shape as original
mask = np.zeros((img.shape[0], img.shape[1]), np.uint8)
mask = cv2.drawContours(mask,[c],0,255, -1)

enter image description here

# dilation to avoid border effects
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
dilate = cv2.dilate(mask, kernel, iterations=1)

img2[dilate == 255] = (255, 255, 255)

enter image description here

Another example:

Input:

enter image description here

Result:

enter image description here

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87