'How to use a color bar to measure corresponding RGB values with Numpy or opencv

I am trying to measure corresponding "real" values of an RGB image from an RGB color bar.

enter image description here enter image description here

The color bar is several pixel large and I am wondering what is the best way to represent it. The solution I have currently is to average them along the width.

import cv2
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

img = cv2.cvtColor(cv2.imread('data/dark_img.tif'), cv2.COLOR_BGR2RGB)
color_bar = cv2.cvtColor(cv2.imread('data/c_scale.tif'), cv2.COLOR_BGR2RGB)


# average colors over the bar width to get unique rgb values over the scale length
color_profile = color_bar.mean(axis=1, dtype=int)
scale_max = 1000  # color bar matches values between 0 and 1000
real_values = np.linspace(scale_max, 0, color_profile.shape[0])


def closest_rgb(img_rgb, color_profile_rgb):
    """get indices of color bar array closest to RGB values in imag"""
    img_rgb = img_rgb[:, :, np.newaxis, :]
    rgb_distances = np.sqrt(np.sum((img_rgb - color_profile_rgb) ** 2, axis=-1))
    min_indices = rgb_distances.argmin(-1)
    return min_indices


indices = closest_rgb(img, color_profile)
mapped_values = real_values[indices]

sns.stripplot(data=mapped_values)

Is there a more accurate way?



Solution 1:[1]

This may be what you are looking for

I guess no need to convert to HSV

import cv2
import numpy as np

box = cv2.imread(r'C:\somepath\blue_square.png')
strip = cv2.imread(r'C:\somepath\color_strip.png')

# Convert color to gray -> every color has its unique gray representation 
# y = kr*R + kg*G + kb*B where kr,kg,kb are unique
box_gray = cv2.cvtColor(box,cv2.COLOR_BGR2GRAY)
strip_gray = cv2.cvtColor(strip,cv2.COLOR_BGR2GRAY)

# take average of the box and set +- 10% tolerance to search
box_gray_avg = np.average(box_gray)
lo_lim = box_gray_avg*0.9
hi_lim = box_gray_avg*1.1

# lets match to the middle 1 pixel thick of the strip
rows, cols = strip_gray.shape
strip_thin_gray = strip_gray[:,cols//2]

# find the indexes where the match 
indx = np.where((strip_thin_gray>lo_lim) & (strip_thin_gray<hi_lim))

print(indx)


Output (array([ 98, 99, 100, 101, 102, 103], dtype=int64),)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 balu