반응형

텐서플로우를 사용한 색 인식 코드를( Color Recognition ) 테스트해본 결과입니다.

코드 출처 : https://github.com/dedo24397/ColorClassifier 



2018. 10. 14  최초작성

2021. 02. 14  최종작성 - Python 3.7, Tensorflow 2.4.0, OpenCV 4.4.0 에서 테스트 



 




1. 다음 세 가지 패키지를 설치합니다.

 

pip3 install --upgrade tensorflow

pip3 install opencv-contrib-python

pip3 install python-firebase



Python 3.7에서는 python-firebase 패키지를 다음처럼 설치해야 합니다. Python 3.8 이상에서는 테스트 못해봤습니다. 

 

pip install git+https://github.com/ozgur/python-firebase



다음과 같은 에러가 나기 때문입니다.

 

    from firebase import firebase

  File "C:\Users\webnautes\AppData\Local\Programs\Python\Python37\lib\site-packages\firebase\__init__.py", line 3

    from .async import process_pool

              ^

SyntaxError: invalid syntax

 

 

 

2. 순서대로 다음 세가지 코드를 실행시키면 데이터 가져오기와 훈련이 됩니다. 

  • getData.py

  • processData.py

  • train.py

 

학습시켜도 정확도가 80%를 넘지는 못합니다. 




3. predict.py 코드를 실행시키면 빨간색을 인식하여 red-ish를 출력합니다. 




4. color_recognition.py 코드를 실행 후  이미지에서 마우스로 클릭하면 해당 색 이름을 출력합니다.

유튜브 영상에서는 다음 이미지를 사용했습니다. 

 





getData.py

from firebase import firebase
import json



db = firebase.FirebaseApplication("https://color-classification.firebaseio.com", None)
jsonData = db.get("/colors", None)
data = []

for user in jsonData.keys():
    entry = {}
    entry['r'] = jsonData[user]['r']
    entry['g'] = jsonData[user]['g']
    entry['b'] = jsonData[user]['b']
    entry['label'] = jsonData[user]['label']
    data.append(entry)


json.dump({"data":data}, open("data.json", "w"))

 


processData.py

from firebase import firebase
import json
import numpy as np

data = json.load(open("data.json"))['data']
cols = []
lbls = []
labelsValues = [
    "red-ish",
    "green-ish",
    "blue-ish",
    "orange-ish",
    "yellow-ish",
    "pink-ish",
    "purple-ish",
    "brown-ish",
    "grey-ish"
]
for submission in data:
    color = []
    color.append(submission["r"] / 255)
    color.append(submission["g"] / 255)
    color.append(submission["b"] / 255)
    cols.append(color)
    lbls.append(labelsValues.index(submission["label"]))

colors = np.array(cols, dtype=np.float32)
labels = np.array(lbls, dtype=np.uint8)
np.savez_compressed("processedData", colors = colors, labels = labels)



train.py


import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import tensorflow as tf
import numpy as np
from random import randint
import json

colors = None
labels = None
data_size = 0


# tf.enable_eager_execution()


with tf.device("/cpu:0"):
    with np.load("processedData.npz") as savedData:
        colors = np.array(savedData['colors'], dtype=np.float32)
        labels = tf.one_hot(savedData['labels'], 9, dtype=tf.uint8).numpy()
        data_size = len(savedData['colors'])


train_size = int(data_size*0.8)
test_size = validation_size = int((data_size - train_size)/2)

indexes = [randint(0, data_size-1) for i in range(train_size)]
colors_train = tf.constant([colors[i] for i in indexes])
labels_train = tf.constant([labels[i] for i in indexes])
test_indexes = []
for i in range(0, data_size):
    if not (i in indexes):
        test_indexes.append(i)
test_indexes = [test_indexes[randint(0, test_size-1)] for i in range(test_size)]
colors_test = tf.constant([colors[i] for i in test_indexes])
labels_test = tf.constant([labels[i] for i in test_indexes])
validation_indexes = []
for i in range(0, data_size):
    if not (i in test_indexes) and not (i in indexes):
        validation_indexes.append(i)
validation_indexes = [validation_indexes[randint(0, validation_size-1)]  for i in range(validation_size)]
colors_validation = tf.constant([colors[i] for i in validation_indexes])
labels_validation = tf.constant([labels[i] for i in validation_indexes])

np.savez_compressed("dataset", train_x = colors_train.numpy(), train_y = labels_train.numpy(), test_x = colors_test.numpy(),
        test_y = labels_test.numpy(), validation_x = colors_validation.numpy(), validation_y = labels_validation.numpy())

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(64, input_shape=(3,),activation=tf.nn.relu),
    tf.keras.layers.Dense(9, activation=tf.nn.softmax)
])

model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

print("Training:")
model.fit(colors_train, tf.cast(labels_train, tf.float32), epochs=15, batch_size=32)
print("Training ended. Validating:")
model.fit(colors_validation, tf.cast(labels_validation, tf.float32), epochs=15, batch_size=32)
json.dump({'model':model.to_json()}, open("model.json", "w"))
model.save_weights("model_weights.h5")

 

predict.py

import tensorflow as tf
import numpy as np
import json


labelsValues = [
    "red-ish",
    "green-ish",
    "blue-ish",
    "orange-ish",
    "yellow-ish",
    "pink-ish",
    "purple-ish",
    "brown-ish",
    "grey-ish"
]


# tf.enable_eager_execution()


#LOADING MODEL
model = tf.keras.models.model_from_json(json.load(open("model.json"))["model"], custom_objects={})
model.load_weights("model_weights.h5")
print("Loaded model from disk")

r = 254 / 255
g = 0 / 255
b = 2 / 255
# 254 0 2 orange-ish
# 12 255 2 red-ish
t = np.argmax(model.predict(tf.constant([[r, g, b]], dtype=tf.float32)))
print(labelsValues[t])



color_recognition.py

import cv2 as cv
import tensorflow as tf
import numpy as np
import json

hsv = 0
lower_blue1 = 0
upper_blue1 = 0
lower_blue2 = 0
upper_blue2 = 0
lower_blue3 = 0
upper_blue3 = 0


labelsValues = [
    "red-ish",
    "green-ish",
    "blue-ish",
    "orange-ish",
    "yellow-ish",
    "pink-ish",
    "purple-ish",
    "brown-ish",
    "grey-ish"
]



def mouse_callback(event, x, y, flags, param):
    global hsv, lower_blue1, upper_blue1, lower_blue2, upper_blue2, lower_blue3, upper_blue3

    # 마우스 왼쪽 버튼 누를시 위치에 있는 픽셀값을 읽어와서 HSV로 변환합니다.
    if event == cv.EVENT_LBUTTONDOWN:
        print(img_color[y, x])
        color = img_color[y, x]

        one_pixel = np.uint8([[color]])
        hsv = cv.cvtColor(one_pixel, cv.COLOR_BGR2HSV)
        hsv = hsv[0][0]

        # HSV 색공간에서 마우스 클릭으로 얻은 픽셀값과 유사한 필셀값의 범위를 정합니다.
        if hsv[0] < 10:
            print("case1")
            lower_blue1 = np.array([hsv[0]-10+180, 30, 30])
            upper_blue1 = np.array([180, 255, 255])
            lower_blue2 = np.array([0, 30, 30])
            upper_blue2 = np.array([hsv[0], 255, 255])
            lower_blue3 = np.array([hsv[0], 30, 30])
            upper_blue3 = np.array([hsv[0]+10, 255, 255])
            #     print(i-10+180, 180, 0, i)
            #     print(i, i+10)

        elif hsv[0] > 170:
            print("case2")
            lower_blue1 = np.array([hsv[0], 0, 0])
            upper_blue1 = np.array([180, 255, 255])
            lower_blue2 = np.array([0, 0, 0])
            upper_blue2 = np.array([hsv[0]+10-180, 255, 255])
            lower_blue3 = np.array([hsv[0]-10, 0, 0])
            upper_blue3 = np.array([hsv[0], 255, 255])
            #     print(i, 180, 0, i+10-180)
            #     print(i-10, i)
        else:
            print("case3")
            lower_blue1 = np.array([hsv[0], 30, 30])
            upper_blue1 = np.array([hsv[0]+10, 255, 255])
            lower_blue2 = np.array([hsv[0]-10, 30, 30])
            upper_blue2 = np.array([hsv[0], 255, 255])
            lower_blue3 = np.array([hsv[0]-10, 30, 30])
            upper_blue3 = np.array([hsv[0], 255, 255])
            #     print(i, i+10)
            #     print(i-10, i)

        print(hsv[0])
        print("@1", lower_blue1, "~", upper_blue1)
        print("@2", lower_blue2, "~", upper_blue2)
        print("@3", lower_blue3, "~", upper_blue3)



        r = color[2]/ 255
        g = color[1]/ 255
        b = color[0]/ 255

        print(r, g, b)


        result = np.argmax(model.predict(tf.constant([[r, g, b]], dtype=tf.float32)))
        print(labelsValues[result])



cv.namedWindow('img_color')
cv.setMouseCallback('img_color', mouse_callback)



#tf.enable_eager_execution()

#LOADING MODEL
model = tf.keras.models.model_from_json(json.load(open("model.json"))["model"], custom_objects={})
model.load_weights("model_weights.h5")
print("Loaded model from disk")



while(True):
    img_color = cv.imread('0.jpg')
    height, width = img_color.shape[:2]
    img_color = cv.resize(img_color, (width, height), interpolation=cv.INTER_AREA)

    # 원본 영상을 HSV 영상으로 변환합니다.
    img_hsv = cv.cvtColor(img_color, cv.COLOR_BGR2HSV)

    # 범위 값으로 HSV 이미지에서 마스크를 생성합니다.
    img_mask1 = cv.inRange(img_hsv, lower_blue1, upper_blue1)
    img_mask2 = cv.inRange(img_hsv, lower_blue2, upper_blue2)
    img_mask3 = cv.inRange(img_hsv, lower_blue3, upper_blue3)
    img_mask = img_mask1 | img_mask2 | img_mask3


    # 마스크 이미지로 원본 이미지에서 범위값에 해당되는 영상 부분을 획득합니다.
    img_result = cv.bitwise_and(img_color, img_color, mask=img_mask)





    cv.imshow('img_color', img_color)
    cv.imshow('img_mask', img_mask)
    cv.imshow('img_result', img_result)


    # ESC 키누르면 종료
    if cv.waitKey(1) & 0xFF == 27:
        break


cv.destroyAllWindows()
반응형

포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
질문을 남겨주면 가능한 빨리 답변드립니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 ~~

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요 ^^

  1. sad 2019.04.04 16:49

    I'm trying to execute this program on raspberrypi.
    But it doesn't work when I did python train.py.
    Error says, OverflowError: Python int too large to convert to C long .

    I proceed to next step, but error comes out.
    FileNotFoundError: [Errno 2] No such file or directory: 'model.json'

    Please HELP ME... I am Korean... so reply with Korean please...

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.04.04 23:11 신고

      1. int 타입 문제로 오버플로우가 발생한거 같은데 몇번째 라인에서 발생했는지 알 수 없어서 답하기 어렵네요.

      2. model.json 파일은 train.py 코드가 문제 없이 동작해야 저장됩니다.

  2. 2021.02.14 22:02

    비밀댓글입니다

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2021.02.14 22:27 신고

      다음 포스트를 참고하세요

      OpenCV Python 예제 - 컨투어 내부의 색 검출하기(Detect color inside contour area)
      https://webnautes.tistory.com/1326

+ Recent posts