1

I have datasets of images of gemstones.I have categorised the gemstones into folders based on their colours.(That is Red, Blue, Pink,Purple,Yellow).

What I want to do is:

I want to train a model using hsv model and opencv to detect the colour of the gemstone.That is whether its blue,purple,pink,yellow or Red and any other colour except to these 5 colours to define as undefined colour

Source Code:(referred https://www.kaggle.com)

import os
import matplotlib.pyplot as plt
import seaborn as sn

import cv2
from random import randint

import numpy as np

CLASSES, gems = [], [] # names of classes, count of images for each class

for root, dirs, files in os.walk('C:/Users/User/Desktop/Research Project/images'):
    f = os.path.basename(root)    # get class name - Red,Blue etc    
        
    if len(files) > 0:
        gems.append(len(files))
        if f not in CLASSES:
            CLASSES.append(f) # add folder name
    
gems_count = len(CLASSES) # 6 = number of classes
print('{} classes with {} images in total'.format(len(CLASSES), sum(gems)))

img_w, img_h = 220, 220    # width and height of image
train_dir = 'C:/Users/User/Desktop/Gem/images/train'

def read_imgs_lbls(_dir):
    Images, Labels = [], []
    for root, dirs, files in os.walk(_dir):
        f = os.path.basename(root)  # get class name - Red, Blue, etc       
        for file in files:
            Labels.append(f)
            try:
                image = cv2.imread(root+'/'+file)              # read the image (OpenCV)
                image = cv2.resize(image,(int(img_w*1.5), int(img_h*1.5)))       # resize the image (images are different sizes)
                image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # converts an image from BGR color space to HSV
                Images.append(image)
            except Exception as e:
                print(e)
    Images = np.array(Images)
    return (Images, Labels)

def get_class_index(Labels):
    for i, n in enumerate(Labels):
        for j, k in enumerate(CLASSES):    # foreach CLASSES
            if n == k:
                Labels[i] = j
    Labels = np.array(Labels)
    return Labels

Train_Imgs, Train_Lbls = read_imgs_lbls(train_dir)
Train_Lbls = get_class_index(Train_Lbls)
print('Shape of train images: {}'.format(Train_Imgs.shape))
print('Shape of train labels: {}'.format(Train_Lbls.shape))

dim = 4 

f,ax = plt.subplots(dim,dim) 
f.subplots_adjust(0,0,2,2)
for i in range(0,dim):
    for j in range(0,dim):
        rnd_number = randint(0,len(Train_Imgs))
        cl = Train_Lbls[rnd_number]
        ax[i,j].imshow(Train_Imgs[rnd_number])
        ax[i,j].set_title(CLASSES[cl]+': ' + str(cl))
        ax[i,j].axis('off')

It read the values from the folder names.But I want to add the lower and upper values of each colour to the training model as in the link below.(Referred how to know if a color is detected on opencv)

import cv2
import numpy as np

img = cv2.imread("img.jpg")

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

lower_val = np.array([37,42,0]) 
upper_val = np.array([84,255,255]) 

# Threshold the HSV image - any green color will show up as white
mask = cv2.inRange(hsv, lower_val, upper_val)

# if there are any white pixels on mask, sum will be > 0
hasGreen = np.sum(mask)
if hasGreen > 0:
    print('Green detected!')

I found the lower and upper limit hsv values of the colours I want as well

          'red': [[9, 255, 255], [0, 50, 70]],             
          'blue': [[128, 255, 255], [90, 50, 70]],
          'yellow': [[35, 255, 255], [25, 50, 70]],
          'purple': [[158, 255, 255], [129, 50, 70]]

can anyone please let me know how can i combine detecting the colour using the hsv values(as in the how to know if a color is detected on opencv ) to the my source code.

I am new to image processing and any help is appreciated.

Thankyou.

jeni
  • 21
  • 1
  • 5
  • Do you have sample images? What is your specific problem to complete the code? – Markus May 05 '22 at 14:13
  • @Markus Yes I got sample images of gemstones from https://www.kaggle.com. In the code that i have tried it trains the model by getting the folder names.But I want to use hsv color model(lower and upper values of the colors) in the training process as in the article i have found..Iam having a trouble combing the hsv colour model to the code that I have tried. – jeni May 05 '22 at 16:28
  • @Markus My main aim is to use hsv colour model to detect the colour – jeni May 05 '22 at 16:56
  • You mean, you want to detect colours automatically instead of sorting them manually into folders before processing? And all images shall be read from one single folder? – Markus May 05 '22 at 17:54
  • @Markus I have dataset in seperate folders with folder names Blue,Red,Yellow etc..... I want to use hsv color model to detect the colors. In that case do I have to use something like on this article(https://stackoverflow.com/questions/58288014/how-to-know-if-a-color-is-detected-on-opencv)? – jeni May 06 '22 at 02:50
  • The code from the link was already included in your question. I think you already have everything you need. That is why I don't understand the question because it includes the answer. And why do you still nead seperate folders if you can detect the colour automatically? – Markus May 06 '22 at 05:55
  • @Markus The code of mine is under the section 'Source Code'...I have not added The code from the link to my source code,The problem Iam having is how can I combine the code from the link to my source code – jeni May 06 '22 at 06:33
  • @Markus Can u please let me know how can I detect the colour automatically without seperate folders as well – jeni May 06 '22 at 06:47

1 Answers1

1

This code demonstrates how to walk through all files in folder ./images and return the detected colours:

import os
import numpy as np
import cv2

# map colour names to HSV ranges
color_list = [
    ['red', [0, 160, 70], [10, 250, 250]],
    ['pink', [0, 50, 70], [10, 160, 250]],
    ['yellow', [15, 50, 70], [30, 250, 250]],
    ['green', [40, 50, 70], [70, 250, 250]],
    ['cyan', [80, 50, 70], [90, 250, 250]],
    ['blue', [100, 50, 70], [130, 250, 250]],
    ['purple', [140, 50, 70], [160, 250, 250]],
    ['red', [170, 160, 70], [180, 250, 250]],
    ['pink', [170, 50, 70], [180, 160, 250]]
]


def detect_main_color(hsv_image, colors):
    color_found = 'undefined'
    max_count = 0

    for color_name, lower_val, upper_val in colors:
        # threshold the HSV image - any matching color will show up as white
        mask = cv2.inRange(hsv_image, np.array(lower_val), np.array(upper_val))

        # count white pixels on mask
        count = np.sum(mask)
        if count > max_count:
            color_found = color_name
            max_count = count

    return color_found


for root, dirs, files in os.walk('./images'):
    f = os.path.basename(root)

    for file in files:
        img = cv2.imread(os.path.join(root, file))
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        print(f"{file}: {detect_main_color(hsv, color_list)}")

Output with three sample images in subfolder images:

ruby_3.jpg: red
sapphire blue_18.jpg: blue
sapphire pink_18.jpg: pink
sapphire purple_28.jpg: purple
sapphire yellow_9.jpg: yellow

Credits:

Markus
  • 5,976
  • 5
  • 6
  • 21
  • For some images it displays four colors or five colors. like red,yellow,green,blue for a single image(whose original color is blue).Is there a way to solve this issue.For most of the images it displays more than 2 colors as below. sapphire blue_26.jpg ['red', 'yellow', 'pink', 'blue', 'purple', 'red'] sapphire pink_20.jpg ['red', 'yellow', 'pink', 'blue', 'purple', 'red'] sapphire yellow_4.jpg ['red', 'yellow', 'green'] – jeni May 06 '22 at 15:54
  • Yes that can be solved. We could only return the main colour i.e. the colour that has occurs for the most pixels. Do you only need the main colour? Can you share an example image? Do you want that I adjust the answer or do you want to try yourself? – Markus May 06 '22 at 16:39
  • I got the dataset from https://www.kaggle.com/datasets/lsind18/gemstones-images. The colors iam trying to detect are Red,Blue,Pink,Yellow and Purple.(Ruby,Blue Sapphire,Pink Sapphire,Yellow Sapphire and Purple Sapphire data sets are used for this).yes I want only the main colour to be displayed.I tried solving but no success.Highly appreciated if you could help by adjusting. – jeni May 06 '22 at 17:52
  • And if the image is not belong to any of the colors defined then to display as 'Undefined' – jeni May 06 '22 at 19:09
  • I have changed the code to detect only the main colour. And I have added pink as new colour in the colour list (red with low saturation). You will probably have to adjust the colour ranges to meet real gem stone colours. Please check! – Markus May 06 '22 at 19:16
  • ... and "undefined". – Markus May 06 '22 at 19:19
  • @Markus must been back breaking to find the ranges of all those colors :) +1 – Jeru Luke May 06 '22 at 19:45
  • @Markus sorry to trouble you. I have already a trained a model to detect the colour of gemstones using cnn,(source code is available in https://stackoverflow.com/questions/72152635/how-can-i-improve-the-accuracy-rate-of-the-below-trained-model-using-cnn ) And what iam trying is to train another model using hsv and cnn for the same purpose.To that I am using the code that U have suggested above.Can u please let me know by using it can build a cnn? – jeni May 07 '22 at 13:16
  • @jeni Yes, why not? Did you try? – Markus May 07 '22 at 14:29
  • @Markus Yes I tried but have some issues..Let me share what I have tried.And while training the model is it useless resizing and croping the image? – jeni May 07 '22 at 19:11
  • @jeni I'm not yet that experienced with cnn and have no advise about resizing or cropping. Please create a new question with a specific issue so that others can participate! The strength of Stackoverflow is that a lot of different people with different expertise will look at it. Keep in mind that you should repare your question to be as specific as possible. Then you will get a quick and specific answer. – Markus May 07 '22 at 19:30
  • @Markus ok thankyou.. https://stackoverflow.com/questions/72156035/how-to-build-the-cnn-for-the-below-model-in-python – jeni May 08 '22 at 04:43
  • @Markus Is there a way we can measure the acuracy rate of the above color detection training model that u have suggested – jeni May 08 '22 at 10:05
  • @jeni How is accuracy rate defined? – Markus May 08 '22 at 11:41
  • @Markus with number of correct predictions made using the trained model... – jeni May 08 '22 at 14:54
  • @Markus For example in the model that I have trained https://stackoverflow.com/questions/72152635/how-can-i-improve-the-accuracy-rate-of-the-below-trained-model-using-cnn/72153051?noredirect=1#comment127486465_72153051 here i am getting an accuracy rate of 78%..Likewise in the above suggested model how can I detect the accuracy rate of prediction? – jeni May 08 '22 at 14:57
  • @jeni Sorry, but I fear that I can't help you with this. – Markus May 08 '22 at 21:04