[Python|OpenCV]Gemiddelde kleur in cirkel bepalen

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • spork
  • Registratie: Maart 2009
  • Laatst online: 16-07 11:08
Als voorbereiding voor een school opdracht probeer ik Python+openCV onder de knie te krijgen.

Wat ik nu probeer:
-Van een foto met gekleurde plastic bekers het aantal bekers te tellen.
-Van elk van deze bekers een gemiddelde kleur bepalen.
-De kleur tekenen als cirkel om de beker heen.

De code draait en geeft geen errors. Maar helaas klopt de uitvoer niet.
De kleur van de cirkel klopt niet met de kleur van de beker.
Om uit te zoeken waar het mis gaat bepaal ik van 1 beker de gemiddelde kleur nog een keer. Gek genoeg komt hier een andere kleur uit.. 8)7 Inmiddels is dit opgelost met dank aan Kyumia

Welke held kan mijn denk of code fout ontdekken?

Als er nog aanvullende informatie nodig is hoor ik het graag!

Python: Kleurdetectie
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import cv2
import time
import numpy as np

cv2.namedWindow("Kleur",cv2.WINDOW_AUTOSIZE)
cv2.namedWindow("Edges",cv2.WINDOW_AUTOSIZE)

cv2.moveWindow("Kleur",00,00)
cv2.moveWindow("Edges",1280,00)

low_treshold = 100
high_treshold = 130


dp = 2
minDist = 30
param1 = 150
param2 = 45
minRadius = 70
maxRadius = 100

kleurradius = 15

#  retval, img = webcam.read()
while(True):

    
    img = cv2.imread('C:/Users/####/Desktop/Vision_Photos/image1_small.jpg')
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_edges = cv2.Canny(img_gray, low_treshold, high_treshold)
      
    circles = cv2.HoughCircles(img_edges,cv2.HOUGH_GRADIENT, dp, minDist, None, param1, param2, minRadius, maxRadius)
       
    try:
        n = np.shape(circles)
        circles = np.reshape(circles,(n[1],n[2]))
         
        i=0
        colors = np.zeros((len(circles), 3), dtype=np.uint32)

        while (i<len(circles)):
            temp0=[]
            temp1=[]
            temp2=[]
            #print(temp0," - ", temp1," - ", temp0)
            j=0
            k=0
            while (j<2*kleurradius): 
                while(k<2*kleurradius):
                    temp0.append(img[(circles[i][0]-kleurradius+j)][(circles[i][1]-kleurradius+k)][0])
                    temp1.append(img[(circles[i][0]-kleurradius+j)][(circles[i][1]-kleurradius+k)][1])
                    temp2.append(img[(circles[i][0]-kleurradius+j)][(circles[i][1]-kleurradius+k)][2])
                    k+=1
                k=0
                j+=1
                

            colors[i][0]=np.sum(temp0)/len(temp0)
            colors[i][1]=np.sum(temp1)/len(temp1)
            colors[i][2]=np.sum(temp2)/len(temp2)
            i+=1

        i=0
        while(i<len(circles)):
            cv2.circle(img,(circles[i][0],circles[i][1]),circles[i][2],(int(colors[i][0]),int(colors[i][1]),int(colors[i][2])),2)

            i+=1

    ##Vanaf hier bepaal ik de kleur nogmaals##
        t=0
          
        temp0=[]
        temp1=[]
        temp2=[]
            #print(temp0," - ", temp1," - ", temp0)
        j=0
        k=0
        while (j<2*kleurradius): 
                while(k<2*kleurradius):
                    temp0.append(img[(circles[t][0]-kleurradius+j)][(circles[t][1]-kleurradius+k)][0])
                    temp1.append(img[(circles[t][0]-kleurradius+j)][(circles[t][1]-kleurradius+k)][1])
                    temp2.append(img[(circles[t][0]-kleurradius+j)][(circles[t][1]-kleurradius+k)][2])
                    k+=1
                k=0
                j+=1
        cv2.circle(img,(circles[t][0],circles[t][1]),kleurradius,(0,0,0),2)        
        cv2.circle(img,(circles[t][0],circles[t][1]),2*kleurradius,(int(np.sum(temp0)/len(temp0)),int(np.sum(temp0)/len(temp0)),int(np.sum(temp0)/len(temp0))),2) 




    except:
        print("no circles found")
         
    cv2.imshow("Kleur",img) 
    cv2.imshow("Edges",img_edges) 


    break
while(True):
    if(cv2.waitKey(10) == 27):
        print("Er zijn", len(circles), "cirkels gededecteerd")
        break
cv2.destroyAllWindows()


(De rede dat er een wat rare onnodige while loop inzit is omdat dit programma uiteindelijk met een webcam moet gaan functioneren)

Alle reacties


Acties:
  • +2 Henk 'm!

  • Kyumia
  • Registratie: Mei 2010
  • Laatst online: 16-06 20:26
De tweede keer dat je de kleuren bepaalt, bepaal je 3x hetzelfde voor elke channel, dat je andere output krijgt is dan ook niet zo gek:
(int(np.sum(temp0)/len(temp0)),int(np.sum(temp0)/len(temp0)),int(np.sum(temp0)/len(temp0)))
Jouw nested while loop (j en k) hebben een patroon van een vierkant, niet een cirkel, dit kan ook het resultaat beïnvloeden.

Als tip wil ik meegeven: let op de naming. Vervang Temp0, Temp1, Temp2 bijvoorbeeld voor iets als B, G, R. Ga geen Nederlands/Engels mixen in namen van variabelen en ouput, dat leidt tot verwarring en persoonlijk vind ik (en ik denk velen meer) het verschikkelijk om Nederlands te lezen in code.

Also, statements als "np.sum(x) / len(x)" kan vervangen worden door np.average(x)

[ Voor 5% gewijzigd door Kyumia op 12-02-2020 22:58 ]


  • spork
  • Registratie: Maart 2009
  • Laatst online: 16-07 11:08
Kyumia schreef op woensdag 12 februari 2020 @ 22:54:
De tweede keer dat je de kleuren bepaalt, bepaal je 3x hetzelfde voor elke channel, dat je andere output krijgt is dan ook niet zo gek:

[...]
Stom. Daarna was het nog steeds niet dezelfde kleur maar na aanpassing van sum/len naar average krijg ik wel twee keer dezelfde kleur! O+
Jouw nested while loop (j en k) hebben een patroon van een vierkant, niet een cirkel, dit kan ook het resultaat beïnvloeden.
Ik weet het, is een gevalletje goed genoeg. O-)
Het zoekgebied is kleiner dan de cirkel en de beker hebben een overtuigende kleur (IKEA kinder servies).
...en persoonlijk vind ik (en ik denk velen meer) het verschikkelijk om Nederlands te lezen in code.
:o Wat een taalverloedering!
Nee, ik zal er op proberen te letten!

[ Voor 4% gewijzigd door spork op 13-02-2020 15:16 ]


  • Kyumia
  • Registratie: Mei 2010
  • Laatst online: 16-06 20:26
Zou je de foto eens kunnen uploaden?

Acties:
  • 0 Henk 'm!

  • spork
  • Registratie: Maart 2009
  • Laatst online: 16-07 11:08
Uiteraard!


Google Photos


Inmiddels is de code wat aangepast:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# viewer.py
import cv2
import time
import numpy as np




cv2.namedWindow("Color",cv2.WINDOW_AUTOSIZE)
#cv2.namedWindow("Edges",cv2.WINDOW_AUTOSIZE)


cv2.moveWindow("Color",00,00)
#cv2.moveWindow("Edges",1280,00)

#webcam = cv2.VideoCapture(0)
#webcam.set(cv2.CAP_PROP_FRAME_WIDTH,1280) 
#webcam.set(cv2.CAP_PROP_FRAME_HEIGHT,720) # webcam.get(cv2.CAP_PROP_FRAME_WIDTH)






low_treshold = 100
high_treshold = 130


dp = 2
minDist = 30
param1 = 150
param2 = 45
minRadius = 70
maxRadius = 100

ColorArea = 15

#writer = cv2.VideoWriter(filename="C:/Users/Dirk/Desktop/Vision_records/recording.avi", fourcc=cv2.VideoWriter_fourcc('I', 'Y', 'U','V'), fps=15, frameSize=(1280,720), isColor=1)


# meer opties in docs.opencv.org 3.0 # high-levelgui VideoCapture::get

#  retval, img = webcam.read()
while(True):
#    low_treshold = low_treshold + 1
   # param2  += 1
    
    img = cv2.imread('C:/Users/Dirk/Desktop/Vision_Photos/image1_small.jpg')
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_edges = cv2.Canny(img_gray, low_treshold, high_treshold)
      
    circles = cv2.HoughCircles(img_edges,cv2.HOUGH_GRADIENT, dp, minDist, None, param1, param2, minRadius, maxRadius)
       
    try:
        n = np.shape(circles)
        circles = np.reshape(circles,(n[1],n[2]))
         
        i=0
        colors = np.zeros((len(circles), 3), dtype=np.uint32)

        while (i<len(circles)):
            temp0=[]
            temp1=[]
            temp2=[]
            #print(temp0," - ", temp1," - ", temp0)
            j=0
            k=0
            while (j<2*ColorArea): 
                while(k<2*ColorArea):
                    temp0.append(img[(circles[i][0]-ColorArea+j)][(circles[i][1]-ColorArea+k)][0])
                    temp1.append(img[(circles[i][0]-ColorArea+j)][(circles[i][1]-ColorArea+k)][1])
                    temp2.append(img[(circles[i][0]-ColorArea+j)][(circles[i][1]-ColorArea+k)][2])
                    k+=1
                k=0
                j+=1
                
   # print(colors)
            #print(temp0," - ", temp1," - ", temp0)
            colors[i][0]=np.average(temp0)
            colors[i][1]=np.average(temp1)
            colors[i][2]=np.average(temp2)
            i+=1

        i=0
        while(i<len(circles)):
            cv2.circle(img,(circles[i][0],circles[i][1]),circles[i][2],(int(colors[i][0]),int(colors[i][1]),int(colors[i][2])),2)
            cv2.putText(img, str(i),(circles[i][0],circles[i][1]),cv2.FONT_HERSHEY_COMPLEX, 0.50, (0,0,0), 1)
            i+=1
        i=0    



    
        t=8
          
        temp0=[]
        temp1=[]
        temp2=[]
            #print(temp0," - ", temp1," - ", temp0)
        j=0
        k=0
        while (j<2*ColorArea): 
                while(k<2*ColorArea):
                    temp0.append(img[(circles[t][0]-ColorArea+j)][(circles[t][1]-ColorArea+k)][0])
                    temp1.append(img[(circles[t][0]-ColorArea+j)][(circles[t][1]-ColorArea+k)][1])
                    temp2.append(img[(circles[t][0]-ColorArea+j)][(circles[t][1]-ColorArea+k)][2])
                    k+=1
                k=0
                j+=1
        cv2.circle(img,(circles[t][0],circles[t][1]),ColorArea,(0,0,0),2)        
        cv2.circle(img,(circles[t][0],circles[t][1]),2*ColorArea,(int(np.average(temp0)),int(np.average(temp1)),int(np.average(temp2))),2) 




    except:
        print("Geen Cirkels gevonden")
         
    cv2.imshow("Color",img) 
    cv2.imshow("Edges",img_edges) 

#      writer.write(img)
    break
while(True):
    if(cv2.waitKey(10) == 27):
        print("Er zijn", len(circles), "cirkels gededecteerd")
        break
cv2.destroyAllWindows()

[ Voor 247% gewijzigd door spork op 14-02-2020 15:46 ]


Acties:
  • 0 Henk 'm!

  • epic007
  • Registratie: Februari 2004
  • Laatst online: 26-06 16:56
Je zou ook de OpenCV functie mean kunnen gebruiken.

code:
1
2
3
4
5
Scalar cv::mean( InputArray src, InputArray mask = noArray() )      


Python:
retval = cv.mean(src[, mask])


Waarbij mask de region is van de cirkel. Hoe je met maskers werkt staat hier goed uitgelegd.

[ Voor 12% gewijzigd door epic007 op 17-02-2020 10:05 ]


Acties:
  • 0 Henk 'm!

  • spork
  • Registratie: Maart 2009
  • Laatst online: 16-07 11:08
epic007 schreef op maandag 17 februari 2020 @ 09:56:
Je zou ook de OpenCV functie mean kunnen gebruiken.

...

Waarbij mask de region is van de cirkel. Hoe je met maskers werkt staat hier goed uitgelegd.
Ga ik zeker naar kijken!

Inmiddels ben ik zelf een aantal andere wegen in geslagen waaronder conversie naar HSV.
Vervolgens de S en de V op basis van een threshold (achtergrond of niet) op 0 of 255 gezet waardoor alleen de kleur overblijft.

Ik heb de gemiddelde kleur voor nu dus geparkeerd omdat de kleur nu ook zonder gemiddeldes super duidelijk is.

Echter blijft de kleur op de verkeerde plek gepakt worden denk ik?! :? 8)7


code:
1
2
3
4
5
6
7
8
i=0
while(i<len(circles)):
  
  cv2.circle(img,(circles[i][0],circles[i][1]),circles[i][2],(int(img_HUE_BGR[(circles[i][0])][(circles[i][1])][0]),int(img_HUE_BGR[(circles[i][0])][(circles[i][1])][1]),int(img_HUE_BGR[(circles[i][0])][(circles[i][1])][2])),2)
    
  cv2.putText(img, str(i),(circles[i][0],circles[i][1]),cv2.FONT_HERSHEY_COMPLEX, 0.50, (0,0,0), 1)

    i+=1

Hierbij is Circles een (18*3) Array met twee coördinaten en een straal per cirkel.
img_HUE_BGR is mijn kleuren plaatje (Die er afgedrukt uitziet zoals verwacht) weer omgezet naar BGR zodat ik de kleuren kan gebruiken voor het tekenen van de cirkels.

Dus de fout moet volgens mij zitten in:

code:
1
2
3
4
5
(
int(img_HUE_BGR[(circles[i][0])][(circles[i][1])][0]),
int(img_HUE_BGR[(circles[i][0])][(circles[i][1])][1]),
int(img_HUE_BGR[(circles[i][0])][(circles[i][1])][2])
)


Maar als deze coördinaten wel werken om de cirkels zelf op de goede plek te tekenen, waarom dan niet om de kleur te pakken? :?

Het resultaat wat ik momenteel krijg:
Python|OpenCV kleur herkenning

Acties:
  • 0 Henk 'm!

  • spork
  • Registratie: Maart 2009
  • Laatst online: 16-07 11:08
OPGELOST! :)

Als je hebt meegedacht, al dan wel of niet met een reactie, bedankt!

Blijkbaar zijn in de Circle array het x en y coördinaat omgedraaid.

De kloppende kleur per locatie is dus:

code:
1
2
3
4
5
    color[0] = (int(img_HUE_BGR[(circles[i][1])][(circles[i][0])][0]))
    color[1] = (int(img_HUE_BGR[(circles[i][1])][(circles[i][0])][1]))
    color[2] = (int(img_HUE_BGR[(circles[i][1])][(circles[i][0])][2]))

    cv2.circle(img,(circles[i][0],circles[i][1]),circles[i][2], color,2)
Pagina: 1