やりたいこと
以下のテキストでは、AIを用いた画像認識により対象物を分類し、ロボットアームにより仕分けを行っています。
・DOBOT Magician AIx画像認識xロボットアーム制御
上記テキストでは、画像認識によって対象物の領域を取得する際に、カメラの画像をグレースケールに変換した後、2値化して、その後、領域を取得しています。その場合でも、カメラの調整や環境(照明の明るさ、外乱光等)の調整をすることでおおよそ認識することが可能です。
テキストでは、グレースケールした際に明暗がハッキリするように、カメラに映るところに黒い下敷きを敷いています。
ただ、対象物が黒い場合、上記の方法ではうまく認識できないことがあります。
今回は、黒い下敷きを任意の色のついたものに変えて、その色を抜き出すことで対象物と背景を切り分けてみたいと思います。
できたもの
今回は、明るめの緑色の画用紙を背景に使用しました。画用紙の色が抜き出せるように範囲を調整を行いました。色が複雑に入り込んでいるものや外郭が黒いものも正しく認識できています。
プログラム
領域を取得している「shoot_trainingData.py」と「classifier.py」を以下のように修正しています。
修正前
# グレースケールに変換(4-3)
gray = cv2.cvtColor(edframe, cv2.COLOR_BGR2GRAY)
# 1/4サイズに縮小
gray_s = cv2.resize(gray, (int(gray.shape[1]/2), int(gray.shape[0]/2)))
# グレースケール画像を表示する
cv2.imshow('Gray Frame', gray_s)
# 2値化(4-4)
retval, bw = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# 1/4サイズに縮小
bw_s = cv2.resize(bw, (int(gray.shape[1]/2), int(gray.shape[0]/2)))
# 2値化画像を表示する
cv2.imshow('Binary Frame', bw_s)
# 輪郭を抽出(4-5)
# contours : [領域][Point No][0][x=0, y=1]
# cv2.CHAIN_APPROX_NONE: 中間点も保持する
# cv2.CHAIN_APPROX_SIMPLE: 中間点は保持しない
contours, hierarchy = cv2.findContours(bw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# グレースケールに変換(3-4)
gray = cv2.cvtColor(edframe, cv2.COLOR_BGR2GRAY)
# 2値化(3-5)
retval, bw = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# 輪郭を抽出(3-6)
contours, hierarchy = cv2.findContours(bw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
修正後
# グレースケールに変換(4-3)
# gray = cv2.cvtColor(edframe, cv2.COLOR_BGR2GRAY)
# 1/4サイズに縮小
# gray_s = cv2.resize(gray, (int(gray.shape[1]/2), int(gray.shape[0]/2)))
# グレースケール画像を表示する
# cv2.imshow('Gray Frame', gray_s)
# 2値化(4-4)
# retval, bw = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# 1/4サイズに縮小
# bw_s = cv2.resize(bw, (int(gray.shape[1]/2), int(gray.shape[0]/2)))
# 2値化画像を表示する
# cv2.imshow('Binary Frame', bw_s)
# HSV色空間に変換
LOW_COLOR = np.array([ 30, 64, 0])
HIGH_COLOR = np.array([ 90, 255, 255])
hsv = cv2.cvtColor(edframe, cv2.COLOR_BGR2HSV)
# 色を抽出する
ex_img = cv2.inRange(hsv, LOW_COLOR, HIGH_COLOR)
# ノイズ除去
ex_img = cv2.medianBlur(ex_img, 5)
kernel = np.ones((3,3), np.uint8)
ex_img = cv2.dilate(ex_img, kernel, iterations=2)
# 黒白反転
ex_img = cv2.bitwise_not(ex_img)
# 1/4サイズに縮小して表示
ex_img_s = cv2.resize(ex_img, (int(ex_img.shape[1]/2), int(ex_img.shape[0]/2)))
cv2.imshow("ex_img", ex_img_s)
# 輪郭を抽出(4-5)
# contours : [領域][Point No][0][x=0, y=1]
# cv2.CHAIN_APPROX_NONE: 中間点も保持する
# cv2.CHAIN_APPROX_SIMPLE: 中間点は保持しない
# contours, hierarchy = cv2.findContours(bw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours, hierarchy = cv2.findContours(ex_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# グレースケールに変換(3-4)
# gray = cv2.cvtColor(edframe, cv2.COLOR_BGR2GRAY)
# 2値化(3-5)
# retval, bw = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# HSV色空間に変換
LOW_COLOR = np.array([30, 64, 0])
HIGH_COLOR = np.array([90,255,255])
hsv = cv2.cvtColor(edframe, cv2.COLOR_BGR2HSV)
# 色を抽出する
ex_img = cv2.inRange(hsv, LOW_COLOR, HIGH_COLOR)
# ノイズ除去
ex_img = cv2.medianBlur(ex_img, 5)
kernel = np.ones((3,3), np.uint8)
ex_img = cv2.dilate(ex_img, kernel, iterations=2)
# 黒白反転
ex_img = cv2.bitwise_not(ex_img)
# 1/4サイズに縮小して表示
ex_img_s = cv2.resize(ex_img, (int(ex_img.shape[1]/2), int(ex_img.shape[0]/2)))
cv2.imshow("ex_img", ex_img_s)
# 輪郭を抽出(3-6)
# contours, hierarchy = cv2.findContours(bw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours, hierarchy = cv2.findContours(ex_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
抜き出す色の調整
上記、プログラムでは緑色を抜き出す際の調整になっています。
動かす照明環境やそもそも別の色を抜き出したい場合は、以下の部分の調整を行ってください。
# HSV色空間に変換
LOW_COLOR = np.array([30, 64, 0])
HIGH_COLOR = np.array([90,255,255])