GR-SAKURA
GR-KURUMI
GR-COTTON
GR-CITRUS
GR-PEACH
GR-KAEDE
GR-ADZUKI
GR-LYCHEE
GR-ROSE
GR-MANGO(*)
SNShield
Web Compiler
IDE for GR
TOPPERS関連
女子美コラボ
その他
※プロデューサミーティング中
作り方使い方資料
イベント関連
作品記事
体験記事
ライブラリ
ツール
その他・過去ファイル
GR-LYCHEEによる色追跡ロボットを作製したので参考になればと思い公開します。
反響があればプログラムも公開しようと考えています。
動画のURL:https://youtu.be/xEMXjgyl8jY
こんにちは
作者です。
色々あってご返信できずに申し訳ございません。
下記にプログラムを載せています。
もしよろしければご活用ください
/////////////////////////////////////////////////////////////////////////////目標物体色複数検出可能プログラム////////////////////////////////////…
ちょっと作者もRulzに訪れていない気もしますので、少しコメントを残させてください。
以下を参考にしていただければと思います。OpenCVの使い方も色々ありますが、そもそもGR-LYCHEEはRAMが少ないこともあり、その辺との折り合いも大事になってきます。例えばオリジナルの画像サイズとか。
GR-LYCHEEで物体追跡(色検出)ロボ
http://tool-cloud.renesas.com/ja/atelier/detail.php?id=71
OpenCVの応用 輪郭検出、HSV色空間
https://www.renesas.com/jp/ja/products/gadget-renesas/boards/gr-lychee/lychee-project-opencv-contour-detection.html
/////////////////////////////////////////////////////////////////////////////目標物体色複数検出可能プログラム///////////////////////////////////////////////////////////////////////////#include "Labeling.h"#include <Camera.h>#include <opencv.hpp>#include <stdlib.h>#include <LCD.h>//#include <math.h>using namespace cv;
typedef union { uint32_t yuv; uint8_t d[4];} _yuv422pack;
//For input interfaces#define IMAGE_HW 480#define IMAGE_VW 272Camera camera(IMAGE_HW, IMAGE_VW);//#define DATA_SIZE_PER_PIC 2u//For processing//(1)binarizationuint8_t mask[IMAGE_HW * IMAGE_VW]; //ラベリング用マスク#define COLOR_RED 1#define COLOR_BLUE 2#define COLOR_BLACK 3#define COLOR_PINK_AND_ORAGGE 4#define COLOR_GREEN 5#define COLOR_YELLOW 6#define COLOR_PURPLE 7#define COLOR_WHITE 8#define COLOR_GRAY 9#define COLOR_FLESH 10int choose_color=COLOR_RED;//(2)labelingLabelingBS labeling;RegionInfoBS *ri;short *mask2; //ラベリング出力先inline bool detectColor(uint8_t y, uint8_t u, uint8_t v,int color_detect);/* Application variables */Mat frame_bgr;float x_Center[10],y_Center[10];//検出した目標の中心座標int object_found_flag=0;//目標を検出したかどうかの確認//(3)Field angle calculationint duty_y = 512,duty_x=512;//x,y方向サーボの角度int duty_y_pre = 512,duty_x_pre=512;//x,y方向サーボの角度int lcd_x_center=240,lcd_y_center=136;//lcd_x_center=IMAGE_HW/2,lcd_y_center=IMAGE_VW/2をしているのでIMAGE_HW,IMAGE_VWを変更した場合変更して!int x_Center_pre[10],y_Center_pre[10];int i=0;int x1_1[10], y1_1[10], x2_1[10], y2_1[10],x_length[10],y_length[10];//int x_difference[10];short targetlook_on=0;static unsigned long last_time=0;int change_color=0;//For output interfacesScalar cl_lightgreen = Scalar(***, 255, ***);Scalar cl_red = Scalar(0,0,255);//For output interfacesuint8_t lcd_buf[2 * IMAGE_HW * IMAGE_VW];uint8_t bgr_buf [3 * IMAGE_HW * IMAGE_VW] __attribute((section("NC_BSS"),aligned(32)));LCD lcd(IMAGE_HW, IMAGE_VW);
void setup() { camera.begin(); lcd.begin(lcd_buf,IMAGE_HW,IMAGE_VW); //ax12a.begin(BaudRate, DirectionPin, &Serial4); Serial.begin(9600); lcd.clear();}void loop() { /* ax12a.move(ID_y, 512); ax12a.move(ID_x, 512); */ while(1) { //(1)Camera image into cvMat //---------------------------------------------------------- // Input //---------------------------------------------------------- // First is getting frame image from the camera. // Second is flip processing(the camera consists flipped). //---------------------------------------------------------- //Get bufferd image from image pointer(first address). Mat img_raw(IMAGE_VW, IMAGE_HW, CV_8UC2, camera.getImageAdr()); //Flip the raw image Mat img_flip,frame_bgr2; cv::flip(img_raw, img_flip, 0); /* Canny(img_flip,img_raw,50,150); cv::cvtColor(img_raw, frame_bgr2, COLOR_YUV2BGR_YUY2);*/ //---------------------------------------------------------- // Process (1):Binarization //---------------------------------------------------------- // Process the flip image into binary image. // (the size of binary image is 8bit) //---------------------------------------------------------- //uint32_t *srcimg32_2 = (uint32_t *)img_clone.data; //src uint32_t *srcimg32 = (uint32_t *)img_flip.data; //src uint32_t *destimg32 = (uint32_t *)mask; //dest //choose_color=COLOR_RED; binarization(srcimg32, destimg32,choose_color); //---------------------------------------------------------- // Process (2):Labeling //---------------------------------------------------------- // Process to markup labels. // (This function uses "Labeling.h" from Imura Lab.) // (URL : __________________________________________) //---------------------------------------------------------- cv::cvtColor(img_flip, frame_bgr, COLOR_YUV2BGR_YUY2); mask2 = new short[IMAGE_HW * IMAGE_VW]; labeling.Exec((uchar*)mask, mask2, IMAGE_HW, IMAGE_VW, true, 40); if (labeling.GetNumOfResultRegions() > 0) { for(i=0;i<labeling.GetNumOfResultRegions();i++) { //最大の領域が処理対象 ri = labeling.GetResultRegionInfo(i); ri->GetMin(x1_1[i], y1_1[i]);//領域の左上座標を返す。 ri->GetMax(x2_1[i], y2_1[i]);//領域の右下座標を返す。 //ri->GetCenter( x_Center,y_Center );//領域の中央座標を返す。(!=重心) ri->GetCenterOfGravity( x_Center[i],y_Center[i] );//領域の重心を返す。 //x_difference=abs(x_Center[i]-x_Center_pre[i]);//前回の値との比較 ri->GetSize(x_length[i],y_length[i]);//領域のサイズを返す。 //フラグを立てる object_found_flag=1;
} ////////////////////////// //検出した物体の位置から目標物体を選別する。 ////////////////////////// for(i=0;i<labeling.GetNumOfResultRegions();i++) { if( y2_1[i]<=300){ targetlook_on=i; goto OUT; } else { ; } }OUT: //対象の領域を四角で囲む cv::rectangle(frame_bgr, Point(x1_1[targetlook_on], y1_1[targetlook_on]), Point(x2_1[targetlook_on], y2_1[targetlook_on]),cl_red, 2); ////////////////////////// /*int x1=0, y1=0, x2=IMAGE_HW, y2=IMAGE_VW,x_length,y_length,x_difference; //最大の領域が処理対象 ri = labeling.GetResultRegionInfo(0); ri->GetMin(x1, y1);//領域の左上座標を返す。 ri->GetMax(x2, y2);//領域の右下座標を返す。 //ri->GetCenter( x_Center,y_Center );//領域の中央座標を返す。(!=重心) ri->GetCenterOfGravity( x_Center,y_Center );//領域の重心を返す。 x_difference=abs(x_Center-x_Center_pre);//前回の値との比較 ri->GetSize(x_length,y_length);//領域のサイズを返す。 if(x_length>=150||y_length>=150) { //フラグを立てる(目標物体のx方向の大きさが150以上の時) object_found_flag=2; } else if(x_difference>=120) { //フラグを立てる(目標物体の移動距離の前回との差が120以上の時) object_found_flag=3; } else{ //フラグを立てる object_found_flag=1; } //対象の領域を四角で囲む cv::rectangle(frame_bgr, Point(x1, y1), Point(x2, y2),cl_red, 2);*/ last_time=millis(); } //もしなにもみつからなかったとき else { //フラグを立てる object_found_flag=0; //Not detectと表示する。 cv::putText(frame_bgr, "Not detect", Point(15, 55), FONT_HERSHEY_COMPLEX, 1,cl_lightgreen, 2); if(millis()-last_time>3000) { //色の変更を行うための変数を定義して、値を代入する。 if(change_color==0) { choose_color=COLOR_RED; last_time=millis(); change_color=1; } else{ choose_color=COLOR_BLUE; last_time=millis(); change_color=0; } } } //---------------------------------------------------------- // Process (3):目標物体を中央に来るようにサーボを制御する //---------------------------------------------------------- // Process to Field angle calculation //Detects how far the detected object is from the center of the screen //Servo is performing PID control // References(URL : akiracing.com/.../) //object_found_flag=0:何も見つからないとき //object_found_flag=1:目標物体を見つけたとき //object_found_flag=2:目標物体がある程度近づいたとき //object_found_flag=3:目標物体が高速に移動したとき //---------------------------------------------------------- //---------------------------------------------------------- // Output //---------------------------------------------------------- // First choose the image for your kinds. // Second is to convert processed image to lcd output image. // Third is to display the image. //Free memory //---------------------------------------------------------- lcd.BGR2YUV(frame_bgr.data, lcd_buf, IMAGE_HW, IMAGE_VW); delete[] mask2; }}inline bool detectColor(uint8_t y, uint8_t u, uint8_t v,int color_detect){ switch(color_detect) { case 1: /////////////////////////////////////////////////////////////////// //赤色検出 /////////////////////////////////////////////////////////////////// if(y<=180){ if (165 <= v && u <= 115) return true; else return false;} else return false; break; case 2: /////////////////////////////////////////////////////////////////// //青色検出 /////////////////////////////////////////////////////////////////// if (130 >= v && u >=165 ) return true; else return false; break; case 3: /////////////////////////////////////////////////////////////////// //黒色検出 /////////////////////////////////////////////////////////////////// /*if (v<=150&&v>=100){ if(u >=150&&u<=100)*/ if(y<=16){ if(v<=160&&v>=60) return true; else return false;} else return false; break; case 4: /////////////////////////////////////////////////////////////////// //ピンク,オレンジ色検出(赤っぽい色すべて検出) /////////////////////////////////////////////////////////////////// if (v>=170 && y <= 150) return true; else return false; break; case 5: /////////////////////////////////////////////////////////////////// //蛍光緑色検出 /////////////////////////////////////////////////////////////////// if (v<=105 && u <= 105) return true; else return false; break; case 6: /////////////////////////////////////////////////////////////////// //黄色検出 /////////////////////////////////////////////////////////////////// if(y>=180){ if ((v>=130&&v<=170)){ if(u <= 90){ return true; } else{ return false; } } else return false; } else return false; break; case 7: /////////////////////////////////////////////////////////////////// //紫色検出 /////////////////////////////////////////////////////////////////// if (v>=120 && u >=135 ){ if(y<=130) return true;} else return false; break; case 8: /////////////////////////////////////////////////////////////////// //白色検出(明るいところのみ) /////////////////////////////////////////////////////////////////// //if ((v>=118&&v<=138)&& (u >= 118)&&u<=138) if(y>=195) return true; else return false; break; case 9: /////////////////////////////////////////////////////////////////// //アルミニウム色検出(不完全) /////////////////////////////////////////////////////////////////// if(y>=115&&y<=125){ if (v>=120&&v<=135){ if(u >= 120&&u<=135){ return true; }else{ return false; } }else{ return false; } }else{ return false; } break; case 10://///////////////////////////////////////////////////////////////////肌色検出/////////////////////////////////////////////////////////////////// if(y>=100&&y<=175){ if (v>=140&&v<=205){ if(u >=80&&u<=110){ return true; }else{ return false; } }else{ return false; } }else{ return false; } break; default: break; } return false;}inline bool binarization(uint32_t *srcimg32, uint32_t *dstimg32,int detectcolor){ _yuv422pack data0,data1; //YUV color data at a pixel int pixels=IMAGE_HW * IMAGE_VW * 2; for (int x = 0; x < pixels; x += 8) { //get yuv data from pointer data0.yuv = *srcimg32++; data1.yuv = *srcimg32++; uint8_t y0 = data0.d[0]; uint8_t u0 = data0.d[1]; uint8_t v0 = data0.d[3]; uint8_t y1 = data1.d[0]; uint8_t u1 = data1.d[1]; uint8_t v1 = data1.d[3]; uint32_t c = 0; if(detectColor(y0, u0,v0,detectcolor)) { c=0xffff; } else { c=0; } if(detectColor(y1, u1,v1,detectcolor)) { c=c|0xffff0000; } else { c=c&0x0000ffff; } //next addr; *dstimg32++=c; } return 0;}