10

After remove captcha's background.
The image remain digits and noise.
Noise line is all in one color : RGB(127,127,127)
And then using morphology method.

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
    self.im = cv2.morphologyEx(self.im, cv2.MORPH_CLOSE, kernel)

Some part of digit will be remove.
How to use morphologyEx() remove only color in RGB(127,127,127) ?

enter image description here enter image description here

Yich Lin
  • 435
  • 1
  • 7
  • 22

3 Answers3

12

In order to eliminate color within a particular range you have to use cv2.inRange() function.

Here is the code:

lower = np.array([126,126,126])  #-- Lower range --
upper = np.array([127,127,127])  #-- Upper range --
mask = cv2.inRange(img, lower, upper)
res = cv2.bitwise_and(img, img, mask= mask)  #-- Contains pixels having the gray color--
cv2.imshow('Result',res)

This is what I got for the two images you have:

Image 1:

enter image description here

Image 2:

enter image description here

You carry on from here.

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

COLOR RANGE

color_dict_HSV = {'black': [[180, 255, 30], [0, 0, 0]],
              'white': [[180, 18, 255], [0, 0, 231]],
              'red1': [[180, 255, 255], [159, 50, 70]],
              'red2': [[9, 255, 255], [0, 50, 70]],
              'green': [[89, 255, 255], [36, 50, 70]],
              'blue': [[128, 255, 255], [90, 50, 70]],
              'yellow': [[35, 255, 255], [25, 50, 70]],
              'purple': [[158, 255, 255], [129, 50, 70]],
              'orange': [[24, 255, 255], [10, 50, 70]],
              'gray': [[180, 18, 230], [0, 0, 40]]}

CREDITS:

Ali Hashemian

HOW TO REMOVE A COLOR FROM YOUR IMAGE USING OPENCV

Since most of you would like to do that, i.e. in my case the task was to remove blue color from the image, I used the following code, to remove blue ink stamps and, blue tick marks from my image in order for proper OCR using Tesseract.

[COLOR REMOVAL] CODE

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# image path:    
#path = "D://opencvImages//"
#fileName = "out.jpg"

# Reading an image in default mode:
inputImage = cv2.imread('0.jpg')

# Convert RGB to grayscale:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)

# Convert the BGR image to HSV:
hsvImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2HSV)

# Create the HSV range for the blue ink:
# [128, 255, 255], [90, 50, 70]
lowerValues = np.array([90, 50, 70])
upperValues = np.array([128, 255, 255])

# Get binary mask of the blue ink:
bluepenMask = cv2.inRange(hsvImage, lowerValues, upperValues)
# Use a little bit of morphology to clean the mask:
# Set kernel (structuring element) size:
kernelSize = 3
# Set morph operation iterations:
opIterations = 1
# Get the structuring element:
morphKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))
# Perform closing:
bluepenMask = cv2.morphologyEx(bluepenMask, cv2.MORPH_CLOSE, morphKernel, None, None, opIterations, cv2.BORDER_REFLECT101)

# Add the white mask to the grayscale image:
colorMask = cv2.add(grayscaleImage, bluepenMask)
_, binaryImage = cv2.threshold(colorMask, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imwrite('bwimage.jpg',binaryImage)
thresh, im_bw = cv2.threshold(binaryImage, 210, 230, cv2.THRESH_BINARY)
kernel = np.ones((1, 1), np.uint8)
imgfinal = cv2.dilate(im_bw, kernel=kernel, iterations=1)
cv2.imshow(imgfinal)

BEFORE [Original Image]

Original Image

Blue Mark Extraction

Blue Tick Marks Determined

Final Image

enter image description here

Here you can see that all of the tick marks are almost, removed the reason is that because there is always room for improvement, but this, as it seems, is the best we can get because even removing these little marks is not going to have a profound effect on the OCR using Tesseract.

HOPE THAT HELPS!

  • 1
    Hi, Your code was really helpful for extracting one color from an image. But how can I extract TWO colors at the same time? say if the original image had red and blue marks. I appreciate your response – Won Chul Chung Jun 30 '21 at 07:30
  • @WonChulChung You can do that by first making a mask for the red color, then make a mask for the blue color, then remove the first mask from the original image replace all values with white and then use the second mask (red) and remove all red pixels to white, hope this helps someone else as well. – Muneeb Ahmad Khurram Jan 27 '23 at 04:05
3

Here is my solution.
Your answer is obvious better than my.

 def mop_close(self):
    def morphological(operator=min):
        height, width, _ = self.im.shape
        # create empty image
        out_im = np.zeros((height,width,3), np.uint8)
        out_im.fill(255) # fill with white
        for y in range(height):
            for x in range(width):
                try:
                    if self.im[y,x][0] ==127 and self.im[y,x][1] ==127 and self.im[y,x][2] ==127:
                        nlst = neighbours(self.im, y, x)

                        out_im[y, x] = operator(nlst,key = lambda x:np.mean(x))
                    else:
                        out_im[y,x] = self.im[y,x]
                except Exception as e:
                    print(e)
        return out_im

    def neighbours(pix,y, x):
        nlst = []
        # search pixels around im[y,x] add them to nlst
        for yy in range(y-1,y+1):
            for xx in range(x-1,x+1):
                try:
                    nlst.append(pix[yy, xx])
                except:
                    pass
        return np.array(nlst)

    def erosion(im):
        return morphological(min)

    def dilation(im):
        return morphological(max)

    self.im = dilation(self.im)
    self.im = erosion(self.im)

final result: enter image description here enter image description here

Yich Lin
  • 435
  • 1
  • 7
  • 22