skip to Main Content

I have high number of JPG images in specific folder that I want to keep only #c7d296 color in my images and fill all other remaining areas in images with white color.
for this I can’t use Photoshop because I have high number of JPG images and it get me a lot of time! (about 29000 JPG images).
for this I should use color range tool in python script.

my images are like following sample:
enter image description here

I wrote following script for this process:

import cv2
import os
import numpy as np
import keyboard

def keep_color_only(input_file, output_directory, color_range, fuzziness):
    try:
        # Read the input image
        img = cv2.imread(input_file)

        # Convert image to HSV color space
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

        # Define lower and upper bounds for the color range
        lower_color = np.array(color_range[0])
        upper_color = np.array(color_range[1])

        # Threshold the HSV image to get only desired colors
        mask = cv2.inRange(hsv, lower_color, upper_color)

        # Invert the mask
        mask_inv = cv2.bitwise_not(mask)

        # Create a white background image
        white_background = np.full_like(img, (255, 255, 255), dtype=np.uint8)

        # Combine the original image with the white background using the mask
        result = cv2.bitwise_and(img, img, mask=mask)
        result = cv2.bitwise_or(result, white_background, mask=mask_inv)

        # Output file path
        output_file = os.path.join(output_directory, os.path.basename(input_file))

        # Save the resulting image
        cv2.imwrite(output_file, result)

    except Exception as e:
        print(f"Error processing {input_file}: {str(e)}")

def process_images(input_directory, output_directory, color_range, fuzziness):
    # Create output directory if it doesn't exist
    if not os.path.exists(output_directory):
        os.makedirs(output_directory)

    # Process each JPG file in the input directory
    for filename in os.listdir(input_directory):
        if filename.lower().endswith('.jpg'):
            input_file = os.path.join(input_directory, filename)
            keep_color_only(input_file, output_directory, color_range, fuzziness)

            # Check for 'F7' key press to stop the process
            if keyboard.is_pressed('F7'):
                print("Process stopped by user.")
                return

def main():
    input_directory = r'E:DesktopinfCROP'
    output_directory = r'E:DesktopinfOUTPUT'

    # Color range in HSV format
    color_range = [(75, 90, 160), (95, 255, 255)]  # Lower and upper bounds for HSV color range
    fuzziness = 80

    process_images(input_directory, output_directory, color_range, fuzziness)
    print("Color removal completed.")

if __name__ == "__main__":
    main()

Note that fuzziness of color range must set on 80
script working good but whole of output images fill by white color. this mean output images just have a empty white screen and no any #c7d296 color area keep!

where is my script problem?

2

Answers


  1. It looks like the main issue is how you’re combining the original image with the white background using the mask. Specifically, the way you’re applying the mask to the original image and then combining it with the white background might not be isolating the desired color correctly.

    Here’s a simpler approach to fix this:

    1. Ensure the Mask Correctly Isolates the Desired Color: Make sure the mask correctly identifies the desired color by creating a binary image where the desired color is white and everything else is black.

    2. Fill the Rest with White: Once you’ve isolated the desired color using the mask, use it to fill the rest of the image with white.

    Ensure the correct order and replace your code.

    From

    # Threshold the HSV image to get only desired colors
    mask = cv2.inRange(hsv, lower_color, upper_color)
    
    # Invert the mask
    mask_inv = cv2.bitwise_not(mask)
    
    # Create a white background image
    white_background = np.full_like(img, (255, 255, 255), dtype=np.uint8)
    

    To

    # Threshold the HSV image to get only desired colors
    mask = cv2.inRange(hsv, lower_color, upper_color)
    
    # Create a white background image
    white_background = np.full_like(img, (255, 255, 255), dtype=np.uint8)
    
    # Combine the original image with the white background using the mask
    # First, invert the mask to get the inverse mask
    mask_inv = cv2.bitwise_not(mask)
    
    Login or Signup to reply.
  2. I know you tagged with python but this is miles simpler with ImageMagick which can be installed on macOS, Linux and Windows for free.

    So, basically you want a command like this:

    magick 3KPrGAEl.jpg -fill white -fuzz 8% +opaque "#c7d296" result.jpg
    

    That says… "take your input image, and fill with white, anything that is not within 8% of your green colour in the RGB colour cube, save the result as result.jpg"

    enter image description here


    Unfortunately, JPEG is a really poor choice for blocky, computer-generated images and it blurs colours and details and makes a heck of a mess, leaving artefacts everywhere. If you could get the images as PNG, you would do better.

    Alternatively, you could run a 3×3 median filter to remove small artefacts:

    magick 3KPrGAEl.jpg -fill white -fuzz 8% +opaque '#c7d296'  -statistic median 3 result.png
    

    enter image description here

    If you need to remove larger artefacts, change the 3 to a 5 or 7. Note though that you will start to lose the edges of your yellow-greenish shape if you do that.


    Once you have that command working, you can then adapt it to do all your images, using mogrify. Let’s assume you want the output files in a directory called OUTPUT, you can do all your images in one go with:

    mkdir OUTPUT
    magick mogrify -path OUTPUT -fill white -fuzz 8% +opaque "#c7d296" *.jpg
    

    If you are on a decent OS, like macOS or Linux, you can speed this up even more using multiprocessing. Let’s see if my approach interests you before I cover that.


    Note you should consider multiprocessing with your Python solution anyway. Example here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search