I would need to verify if and how much of certain predefined color ranges are present in a image file.
each color range is defined by 6 variables and a counter in a colorRange
class:
hS (hue start)
hE (hue end)
sS (saturation start)
sE (saturation end)
lS (lightness start)
lE (lightness end)
colorCounter
The image can either be a file, or loaded from the camera. Following code loads the image from the camera buffer:
img1 = np.ndarray(buffer=component.data.copy(), dtype=np.uint8,
shape=(component.height, component.width, 1))
img2 = cv2.cvtColor(img1, cv2.COLOR_BayerBG2BGR)
what I would need to do is to scan every n-th pixel (5 is a good starting value), and compare it to every color range. if it falls into that color range, then add +1 to that specific colorCounter
. In the end I go over the Counter of each color range and calculate the presence of that color range in %. The goal is to check the % of analized pixels that fall into each color range. The sum of the colorranges can be greater than 100 since a pixel can fall into multiple colorranges as tehy can be overlapping. (for example a color ragne could be all the reds, and another could be only the dark reds.. a dark red pixel would fall into both ranges, a bright red only in the first one.)
The way I would do it is to check every fifth pixel one by one, convert its rgb value to HSL, and then compare it with all the color ranges. (where if hS > hE then it is wrapping around in the reds)
But it seems a very complicated way to do it and was wondering if there are some premade functions that can do this, or at least partially do this.
So the question is: How can this be done in a smart way?
UPDATE:
this is what I have so far:
hls = cv2.cvtColor(img2, cv2.COLOR_BGR2HLS)
GreenLo = np.array([75, 0, 0])
GreenHi = np.array([155, 1, 1])
pxGreen = cv2.inRange(hls[0:620:5, 0:620:5], GreenLo, GreenHi)
cGreen = cv2.countNonZero(pxGreen)
I followed the advice of @Mark Setchell and came up with this solution:
The color class:
class crateColor(QObject):
cName: str
cId: int
pId: int
hHi: int
hLo: int
lHi: int
lLo: int
sHi: int
sLo: int
pxCnt: int
perc: float
The adopted solution:
green = crateColorClass.crateColor()
green.cName = "EU green"
green.cId = 1
green.pId = 1
green.hLo = 65
green.hHi = 165
green.lLo = 20
green.lHi = 95
green.sLo = 20
green.sHi = 100
colorList.append(green) # REPEATING THIS FOR EACH COLOR.
x1 = 170 # DEFINING THE AREA AND POSITION I AM INTERESTED IN AND EVERY Nth. PIXEL
x2 = 470
y1 = 520
y2 = 610
i = 5
dx = x2-x1
dy = y2-y1
a = int(dx/i)*int(dy/i)
for c in colorList:
if c.hLo > c.hHi: # wrap around 360 for red.
Lo = np.array([c.hLo, c.lLo*2.55, c.sLo*2.55]) # *2.55 to have S and L 0 to 100
Hi = np.array([359, c.lHi*2.55, c.sHi*2.55])
px = cv2.inRange(hls[y1:y2:i, x1:x2:i], Lo, Hi)
c.pxCnt = cv2.countNonZero(px)
Lo = np.array([0, c.lLo * 2.55, c.sLo * 2.55])
Hi = np.array([c.hHi, c.lHi * 2.55, c.sHi * 2.55])
px = cv2.inRange(hls[y1:y2:i, x1:x2:i], Lo, Hi)
c.pxCnt = c.pxCnt + cv2.countNonZero(px)
c.perc = (c.pxCnt/a)*100
else:
Lo = np.array([c.hLo, c.lLo*2.55, c.sLo*2.55])
Hi = np.array([c.hHi, c.lHi*2.55, c.sHi*2.55])
px = cv2.inRange(hls[y1:y2:i, x1:x2:i], Lo, Hi)
c.pxCnt = cv2.countNonZero(px)
c.perc = (c.pxCnt/a)*100
print("cName, cId, perc, pxCnt: ", c.cName, c.cId, c.perc, c.pxCnt)