pythonopencvdata-scienceknn

Color Prediction System with OpenCv Python



enter image description hereHi I am an initial stage developer trying to make a color prediction system, but I came up with some error that I can not understand. I think you could help me with this .... I will share with you my proper code

This is the error: IndexError: index 1 is out of bounds for axis 0 with size 1

The error showing in RGB2HEX(color): function but I am unable to solve it

Here is the Code:

def RGB2HEX(color):
return "#{:02x}{:02x}{:02x}".format(int(color[0]), int(color[1]), int(color[2]))

def get_image(image_path):
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
return image

IMAGE_DIRECTORY = 'C:/Users/Dell/Desktop/CPS 02'
COLORS = {
    'GREEN': [0, 128, 0],
    'BLUE': [0, 0, 128],
    'YELLOW': [255, 255, 0]
}
images = []

for file in os.listdir(IMAGE_DIRECTORY):
    if not file.startswith('.'):
        images.append(get_image(os.path.join(IMAGE_DIRECTORY, file)))

# extracting colors from image 
def get_colors(images, number_of_colors, show_char = True):
for j in range(len(images)):
    modified_image = cv2.resize(images[j], (600, 400), interpolation = cv2.INTER_AREA)
    modified_image = modified_image.reshape(modified_image.shape[0]*modified_image.shape[1],1)

    clf = KMeans(n_clusters = number_of_colors)
    labels = clf.fit_predict(modified_image)

    counts = Counter(labels)

    center_colors = clf.cluster_centers_
    # We get ordered colors by iterating through the keys
    ordered_colors = [center_colors[i] for i in counts.keys()]
    hex_colors = [RGB2HEX(ordered_colors[i]) for i in counts.keys()]
    rgb_colors = [ordered_colors[i] for i in counts.keys()]

# matching an image by its color
def match_image_by_color(image, color, threshold = 60, number_of_colors = 10): 

image_colors = get_colors(image, number_of_colors, False)
selected_color = rgb2lab(np.uint8(np.asarray([[color]])))

select_image = False
for i in range(number_of_colors):
    curr_color = rgb2lab(np.uint8(np.asarray([[image_colors[i]]])))
    diff = deltaE_cie76(selected_color, curr_color)
    if (diff < threshold):
        select_image = True

return select_image

# Selecting an image
def show_selected_images(images, color, threshold, colors_to_match):
index = 1

for i in range(len(images)):
    selected = match_image_by_color(images[i], color, threshold, colors_to_match)
    if (selected):
        plt.subplot(1, 5, index)
        plt.imshow(images[i])
        index += 1

# printing the result 
plt.figure(figsize = (20, 10))
show_selected_images(images, COLORS['BLUE'], 60, 5)

Solution

  • Using this page as a guide for imports and such, I was able to successfully implement your code on some stock images I have AND recreate your error. I think I know what is going on.

    I believe the images you are reading in are single channel (grayscale), not RGB. When you reshape the images, you turn each image into an Nx1 vector -- only a single color channel there. Hence your RGB2HEX() function errors when it references the second dimension of your 1D image vector.

    When I instead read in a three channel (RGB) image, and reshape to an Nx3 matrix, your function successfully executes. I have included full code below. You'll note the two lines (commented out) that can be used with grayscale images to reproduce your error. Obviously comment out the RGB equivalent lines if you want the grayscale version.

    from sklearn.cluster import KMeans
    import matplotlib.pyplot as plt
    import numpy as np
    import cv2
    from collections import Counter
    import os
    import argparse
    
    def RGB2HEX(color):
        return "#{:02x}{:02x}{:02x}".format(int(color[0]), int(color[1]), int(color[2]))
    
    def get_image(image_path):
        image = cv2.imread(image_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        # example to read as grayscale image
        # image = cv2.imread(image_path, 0)
        return image
    
    IMAGE_DIRECTORY = './path/to/images/'
    COLORS = {
        'GREEN': [0, 128, 0],
        'BLUE': [0, 0, 128],
        'YELLOW': [255, 255, 0]
    }
    images = []
    
    for file in os.listdir(IMAGE_DIRECTORY):
        if not file.startswith('.'):
            images.append(get_image(os.path.join(IMAGE_DIRECTORY, file)))
    
    # extracting colors from image 
    def get_colors(images, number_of_colors, show_char = True):
        for j in range(len(images)):
            modified_image = cv2.resize(images[j], (600, 400), interpolation = cv2.INTER_AREA)
            modified_image = modified_image.reshape(modified_image.shape[0]*modified_image.shape[1], 3)
            # example to use with grayscale images        
            # modified_image = modified_image.reshape(modified_image.shape[0]*modified_image.shape[1], 1)
    
            clf = KMeans(n_clusters = number_of_colors)
            labels = clf.fit_predict(modified_image)
    
            counts = Counter(labels)
    
            center_colors = clf.cluster_centers_
            # We get ordered colors by iterating through the keys
            ordered_colors = [center_colors[i] for i in counts.keys()]
            hex_colors = [RGB2HEX(ordered_colors[i]) for i in counts.keys()]
            rgb_colors = [ordered_colors[i] for i in counts.keys()]