I have image with kind of light purple image in background and character in dark blue. My goal is to identify text from the image. So I\'m trying to remove light purple colo
Here is an approach using a pixel array. Pixel arrays are slow, but if speed isn't an issue, they could serve your needs without having to download any outside libraries. Also, pixel arrays are easy to understand.
import pygame
# -- You would load your image as a sprite here. --
# -- But let's create a demonstration sprite instead.--
#
usecolor = (46,12,187,255) # Declare an example color.
sprite = pygame.Surface((10,10)) # Greate a surface. Let us call it a 'sprite'.
sprite.fill(usecolor) # Fill the 'sprite' with our chosen color.
#
# -- Now process the image. --
array = pygame.PixelArray(sprite) # Create a pixel array of the sprite, locking the sprite.
sample = array[5,5] # Sample the integer holding the color values of pixel [5,5]
# We will feed this integer to pygame.Color()
sample_1 = sprite.get_at((5,5)) # Alternately, we can use the .get_at() method.
# Do the same for every pixel, creating a list (an array) of color values.
del array # Then delete the pixel array, unlocking the sprite.
m,r,g,b = pygame.Color(sample) # Note: m is for the alpha value (not used by .Color())
print("\n sample =",sample,"decoded by python.Color() to:")
print(" r >>",r)
print(" g >>",g)
print(" b >>",b)
print("\n or we could use .get_at()")
print(" sample_1 =",sample_1)
print()
exit()
Just test each r,g,b value to see if they fall within some desired range for each color component. Then copy each pixel over to a new surface, replacing all colors that fall within your range with your desired replacement color.
Or you could add, say 75 to each R,G,B color component (if color > 255: color = 255) before placing the pixel in the new image. This would have the effect of fading all colors towards white until the light color is gone. Then you could repeat the process subtracting 75 from each remaining pixel (with component values less than 255) to bring the colors forward again. I doubt any decent captcha is so easily defeated, but there you go.
Fun fun!
Since there seems to be a distinguishable shade from the text and the background, color thresholding should work here. The idea is to convert the image to HSV format then use a lower and upper threshold to generate a binary segmented mask then bitwise-and to extract the text. Here's an implementation using Python OpenCV
Using this lower and upper threshold, we obtain this mask
lower = np.array([0, 120, 0])
upper = np.array([179, 255, 255])
Then we bitwise-and with the original image
Finally we threshold to get a binary image with the foreground text in black and the background in white
import numpy as np
import cv2
# Color threshold
image = cv2.imread('1.png')
original = image.copy()
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 120, 0])
upper = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(original,original,mask=mask)
result[mask==0] = (255,255,255)
# Make text black and foreground white
result = cv2.cvtColor(result, cv2.COLOR_BGR2GRAY)
result = cv2.threshold(result, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)[1]
cv2.imshow('mask', mask)
cv2.imshow('result', result)
cv2.waitKey()
You can use this HSV color threshold script to determine the lower and upper thresholds
import cv2
import sys
import numpy as np
def nothing(x):
pass
# Load in image
image = cv2.imread('1.png')
# Create a window
cv2.namedWindow('image')
# create trackbars for color change
cv2.createTrackbar('HMin','image',0,179,nothing) # Hue is from 0-179 for Opencv
cv2.createTrackbar('SMin','image',0,255,nothing)
cv2.createTrackbar('VMin','image',0,255,nothing)
cv2.createTrackbar('HMax','image',0,179,nothing)
cv2.createTrackbar('SMax','image',0,255,nothing)
cv2.createTrackbar('VMax','image',0,255,nothing)
# Set default value for MAX HSV trackbars.
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)
# Initialize to check if HSV min/max value changes
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0
output = image
wait_time = 33
while(1):
# get current positions of all trackbars
hMin = cv2.getTrackbarPos('HMin','image')
sMin = cv2.getTrackbarPos('SMin','image')
vMin = cv2.getTrackbarPos('VMin','image')
hMax = cv2.getTrackbarPos('HMax','image')
sMax = cv2.getTrackbarPos('SMax','image')
vMax = cv2.getTrackbarPos('VMax','image')
# Set minimum and max HSV values to display
lower = np.array([hMin, sMin, vMin])
upper = np.array([hMax, sMax, vMax])
# Create HSV Image and threshold into a range.
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
output = cv2.bitwise_and(image,image, mask= mask)
# Print if there is a change in HSV value
if( (phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
phMin = hMin
psMin = sMin
pvMin = vMin
phMax = hMax
psMax = sMax
pvMax = vMax
# Display output image
cv2.imshow('image',output)
# Wait longer to prevent freeze for videos.
if cv2.waitKey(wait_time) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()