Reputation: 72
I am trying to extract features of multiple images located in a specific folder ('image'). I want to insert this features (grayscale, R,G,B, alpha, height and width) into a table using tabulate package. The main issue is to iterate over the folder and extract the average values of the single Red, Green, Blue channels and, also to obtain the value of gray (if an image is present in that scale). After that, I would like to insert all information into the table. I am not able to do any of this operation. I've tried a this code, but it gives me many pixels values. I'd like to get the average value, so JUST ONE NUMBER for each channel. Please, anybody can help?
import os
import numpy as np
import cv2
for img in os.listdir(image_path):
img = cv2.imread(os.path.join(image_path, img))
r,g,b = cv2.split(img)
rgb_img = cv2.merge((r,g,b))
x,y,z = np.shape(img)
red = np.zeros((x,y,z),dtype=int)
green = np.zeros((x,y,z),dtype=int)
blue = np.zeros((x,y,z),dtype=int)
for i in range(0,x):
for j in range(0,y):
red[i][j][0] = rgb_img[i][j][0]
green[i][j][1]= rgb_img[i][j][1]
blue[i][j][2] = rgb_img[i][j][2]
I don't know any method else, can anybody suggests one? I would really appreciate. Thank you
Upvotes: 2
Views: 4219
Reputation: 167
According to https://sighack.com/post/averaging-rgb-colors-the-right-way the correct way to average RGB color values is to sum their squares rather than just take the mean. Example code in python is given below. Could probably be optimised but works for me.
def get_avg_rgb(img_file: str):
import cv2
img = cv2.imread(img_file)
r_values = img[:, :, 2].flatten()
g_values = img[:, :, 1].flatten()
b_values = img[:, :, 0].flatten()
Rsum = 0
for r in r_values:
Rsum += (float(r) * float(r))
Gsum = 0
for g in g_values:
Gsum += (float(g) * float(g))
Bsum = 0
for b in b_values:
Bsum += (float(b) * float(b))
avgR = math.sqrt((float(Rsum) / len(r_values)))
avgG = math.sqrt((float(Gsum) / len(g_values)))
avgB = math.sqrt((float(Bsum) / len(b_values)))
avgs = [avgR, avgG, avgB]
return avgs
Upvotes: 0
Reputation: 320
If you want the average values of the channels(R, G, B), and finally want to store it in a table using tabulate, you could do the following:
I will be using OpenCV(to load the images) and numpy(cuz why not)
import cv2
import numpy as np
import os
from tabulate import tabulate
images = os.listdir('./Test')
num_images = len(images)
data = [] # using an array is more convenient for tabulate.
for i in range(num_images):
img = cv2.imread('./Test/' + images[i])
avgR = np.mean(img[:,:,2])
avgG = np.mean(img[:,:,1])
avgB = np.mean(img[:,:,0])
data.append([images[i], avgR, avgG, avgB])
print(tabulate(data, headers=['img_name','R', 'G', 'B'], tablefmt='fancy_grid'))
'''
╒════════════╤══════════╤══════════╤══════════╕
│ img_name │ R │ G │ B │
╞════════════╪══════════╪══════════╪══════════╡
│ test1.jpg │ 49.3213 │ 112.408 │ 145.949 │
├────────────┼──────────┼──────────┼──────────┤
│ test2.jpeg │ 93.0038 │ 94.4466 │ 95.0824 │
├────────────┼──────────┼──────────┼──────────┤
│ test3.jpg │ 100.181 │ 71.6575 │ 66.4233 │
╘════════════╧══════════╧══════════╧══════════╛
'''
This is my Directory Structure:
The code is present in the movie scraper directory. Hence i have used the path './Test'. The dot '.' represents the current dir.
Upvotes: 2