Ask Your Question
0

Color of single shape detected,how to detect color of each shape?

asked 2019-02-18 03:35:34 -0500

Erdal.J gravatar image

Hi, Iam trying on Python to detect each shape colors.Code bellow works correctly but detects just one shape color.I need to detect each shape colors..I just defined Blue and Green color boundaries,just to check then I will and for other colors.. Any solution, where Iam doing wrong ? Can anyone help me pls..

import numpy as np
import cv2
rawImage = cv2.imread('C:\Users\erdal.alimovski\Desktop\pict2.jpg')
cv2.imshow('Original Image',rawImage)
cv2.waitKey(0)

gray = cv2.cvtColor(rawImage.copy(), cv2.COLOR_BGR2GRAY)
cv2.imshow('HSV Image',gray)
cv2.waitKey(0)

retval, thresholded = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow('Thresholded Image',thresholded)
cv2.waitKey(0)

medianFiltered = cv2.medianBlur(thresholded,5)
cv2.imshow('Median Filtered Image',medianFiltered)
 cv2.waitKey(0)

cnts, hierarchy = cv2.findContours(medianFiltered, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

lower = np.array([0,50,30], dtype = "uint8")
upper = np.array([90,255,255], dtype = "uint8")

bluelower = np.array([101,50,38],dtype = "uint8")
blueupper = np.array([255,255,110],dtype = "uint8")

for c in cnts:
   M = cv2.moments(c)
   cX = int(M["m10"] / M["m00"])
   cY = int(M["m01"] / M["m00"])
   cc = cX,cY

first = cv2.drawContours(rawImage, [c], -1, (0, 255, 0), 2)

x, y, w, h = cv2.boundingRect(c)
blurred_cnt_image = cv2.blur(rawImage[y:y+h, x:x+w], (5,5))
green_mask = cv2.inRange(blurred_cnt_image, lower, upper)
green_part = cv2.bitwise_and(blurred_cnt_image, blurred_cnt_image, mask = green_mask)
green_part_as_gray = cv2.cvtColor(green_part, cv2.COLOR_BGR2GRAY)
all_pixels = float((green_part.shape[0]*green_part.shape[1])/100)
green_pixels = float(cv2.countNonZero(green_part_as_gray))

blurred_image = cv2.blur(rawImage[y:y+h, x:x+w], (5,5))
blue_mask = cv2.inRange(blurred_image, bluelower, blueupper)
blue_part = cv2.bitwise_and(blurred_image, blurred_image, mask = blue_mask)
blue_part_as_gray = cv2.cvtColor(blue_part, cv2.COLOR_BGR2GRAY)
most_pixels = float((green_part.shape[0]*blue_part.shape[1])/100)
blue_pixels = float(cv2.countNonZero(blue_part_as_gray))

percent = int(green_pixels/all_pixels)
percentb=int(blue_pixels/all_pixels)

if int(percent) > 2:
    cv2.putText(rawImage, str(percent)+"% green",  (cc),cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,255, 255), 2)
else:
    cv2.putText(rawImage, str(percentb) + "% blue",  (cc), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2)



cv2.imshow("raw", rawImage)
cv2.waitKey(10000)

Iam Gettin otuput like this:image description

But I need to detect and other circles color.

edit retag flag offensive close merge delete

Comments

Can you show original?

supra56 gravatar imagesupra56 ( 2019-02-18 09:50:52 -0500 )edit

not sure but these codes would only show one color puttext so you cannot see any other things

  if int(percent) > 2:
    cv2.putText(rawImage, str(percent)+"% green",  (cc),cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,255, 255), 2)
else:
    cv2.putText(rawImage, str(percentb) + "% blue",  (cc), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2)
gino0717 gravatar imagegino0717 ( 2019-02-18 22:01:07 -0500 )edit

@Erdal.J . Change this green to blue:

most_pixels = float((green_part.shape[0]*blue_part.shape[1])/100)

to:

most_pixels = float((blue_part.shape[0]*blue_part.shape[1])/100)
supra56 gravatar imagesupra56 ( 2019-02-19 08:18:23 -0500 )edit

thanks guys, the code below for i in cnts I put ınto loop "for" and I get resault. I need to compute them, I mean I need output for example "2red" and "1 green" circle detected. How I can do it,do you both have any idea?

Erdal.J gravatar imageErdal.J ( 2019-02-19 09:46:58 -0500 )edit

1 answer

Sort by » oldest newest most voted
0

answered 2019-02-19 13:11:00 -0500

supra56 gravatar image

updated 2019-02-20 13:31:27 -0500

@Erdal.J. You should learn to read OpenCV book. You shouldn't gone too far. Reasoning why, you shouldn't write too many cv2.waitKey commands. But cv2.imshow should be ok, but manipulate before waitKey and destroyAllWindows. The putText should be reduced to one instead of multiples. The dictionary is easys, because I reduced codes line by libne.The coded you wrote as above doesn't have while condition block. Without condition. you merely got one colour of blue. Here is code:

#!!usr/bin/env python3
#Raspberry pi 3, Strecth
#Date: 19th February, 2019.
import numpy as np
import cv2

# define the lower and upper boundaries of the colors in the HSV color space
lower = {'red':(0,80,80),
         'green':(35,21,62),
         'blue':(97,100,117),
         'yellow':(23,59,119),
         'orange':(10,100,20)
         }

upper = {'red':(20,255,255), 
         'green':(55,255,255),
         'blue':(117,255,255),
         'yellow':(43,255,255),
         'orange':(30,255,255)
         }

# define standard colors for circle around the object
colors = {'red':(0,0,255),
          'green':(0,255,0),
          'blue':(255,0,0),
          'yellow':(0,255,217),
          'orange':(0,140,255)
          }

font = cv2.FONT_HERSHEY_SIMPLEX
while True:
    # grab the current frame
    frame = cv2.imread('color.jpg')

    blurred = cv2.GaussianBlur(frame,(11,11),0)
    hsv = cv2.cvtColor(blurred,cv2.COLOR_BGR2HSV)
    #for each color in dictionary check object in frame
    for key, value in upper.items():
        kernel = np.ones((9,9),np.uint8)
        mask = cv2.inRange(hsv,lower[key],upper[key])
        mask = cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernel)
        mask = cv2.morphologyEx(mask,cv2.MORPH_CLOSE,kernel)

        #Calculate percentage of pixel colors
        output = cv2.countNonZero(mask)
        res = np.divide(float(output),mask.shape[0]*int(mask.shape[1] / 128))
        percent_colors = np.multiply((res),400) / 10000
        percent=(np.round(percent_colors*100,2))

        cnts = cv2.findContours(mask.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[-2]
        center = None

        if len(cnts) > 0:
            c = max(cnts, key=cv2.contourArea)
            ((x,y), radius) = cv2.minEnclosingCircle(c)
            M = cv2.moments(c)
            center = (int(M["m10"] / M["m00"]),int(M["m01"] / M["m00"]))

            if radius > 0.5:
                cv2.circle(frame,(int(x),int(y)),int(radius),colors[key],2)
                cv2.putText(frame,
                            str(percent) + '% ' +key,
                            (int(x-radius),int(y-radius)),
                            font,
                            0.6,
                            colors[key],
                            2)
    cv2.imwrite('Colors.jpg', frame)
    cv2.imshow("Frame",frame)   
    key = cv2.waitKey(1)
    if key == ord("q"):
        break

camera.release()
cv2.destroyAllWindows()

Output: color_image

If you want index. I still having huge problem. Because I'm using dictionary instead of list. I will have to work around. I couldn't get index ordered. But It will take a time to get back.

for i in range(1,len(key)):
                r =i

            if radius > 0.5:
                cv2.circle(frame,(int(x),int(y)),int(radius),colors[key],2)
                cv2.putText(frame,
                             str(r) + ') '+ key + ' '+ str(percent) + '% '  ,
                            (int(x-radius),int(y-radius)),
                            font,
                            0.6,
                            colors[key],
                            2
                            )

Output: img_Colors

edit flag offensive delete link more

Comments

@supra58 , thanks for replaying and for sugestion..Yes,I will buy it as soon as possible..Iam begginer so I must work hard to understand the main logic. I just put my code above into the loop and I find each colors. And I get the output like youres.

Erdal.J gravatar imageErdal.J ( 2019-02-20 08:52:41 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2019-02-18 03:34:43 -0500

Seen: 55 times

Last updated: Feb 20