본문 바로가기

대외활동/irc src 씨름로봇

[씨름로봇] 영상처리- color tracking(1)

                                                                       color tracking

 

 이전 글에서 말했듯이 로봇을 인식하는 방법이 아래 사진처럼 로봇위의 색 원통을 보고 로봇을 인식을 해야합니당

:서울테크 지능로봇

자 그러면 어떻게 하느냐 처음에는 yolo같은 딥러닝 알고리즘을 써야하나 했지만 그냥 HSV기반으로 컬러 필터를 만들어서 그부분만 객체화 시키면 되긴하죠

 

hsv라는 건 이미지의 RGB 대한 정보를 삼차원 형태로 나눈것인데 H(Hue=>색조), S(Saturation=>채도), V(Value=>명도)

자 그래서 이미지를 hsv로 변환해서 할겁니다. 배운지 꽤되서 기억이 가물가물물


                                                                                소스코드

 

1. header

 #ifndef IMAGE_PROCESSING_H_
#define IMAGE_PROCESSING_H_

#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include "opencv2/imgproc/imgproc.hpp"

using namespace std;
using namespace cv;
class image_process {

    private:
        ros::Publisher pub;
        image_transport::Subscriber sub_img;
	    cv_bridge::CvImagePtr cv_ptr;	
		int minHue,maxHue;
		int minSat,maxSat;
		int minVal,maxVal;
	public:
        image_process(image_transport::ImageTransport *it);
        void ImageCallback(const sensor_msgs::Image::ConstPtr &img); 
		void image_tracking();
		Mat img_;
};

#endif

2. main.cpp

#include "image_processing.h"
image_process::image_process(image_transport::ImageTransport *it){

        sub_img=it->subscribe("/image_raw",1,&image_process::ImageCallback, this);
		
		auto const MASK_WINDOW="mask setting";
		namedWindow(MASK_WINDOW, CV_WINDOW_AUTOSIZE);

		 minHue = 90, maxHue = 140;
    	 minSat = 74, maxSat = 255;
    	 minVal =  0, maxVal = 255;
		
		cvCreateTrackbar("Min Hue", MASK_WINDOW, &minHue, 179);
    	cvCreateTrackbar("Max Hue", MASK_WINDOW, &maxHue, 179);
    	cvCreateTrackbar("Min Sat", MASK_WINDOW, &minSat, 255);
    	cvCreateTrackbar("Max Sat", MASK_WINDOW, &maxSat, 255);
    	cvCreateTrackbar("Min Val", MASK_WINDOW, &minVal, 255);
    	cvCreateTrackbar("Max Val", MASK_WINDOW, &maxVal, 255);
}

void image_process::image_tracking(){
		Mat inputVideo;
		inputVideo=cv_ptr->image.clone();
	 	cv::Mat inputVideoHSV;
        cv::cvtColor(inputVideo, inputVideoHSV, cv::COLOR_BGR2HSV);
        
        Mat mask;
 
        inRange(
            inputVideoHSV, 
            cv::Scalar(minHue, minSat, minVal), 
            cv::Scalar(maxHue, maxSat, maxVal), 
            mask
        );
        Mat resultVideo;
        // params: src1	array, src2 array, output array, mask
        bitwise_and(inputVideo, inputVideo, resultVideo, mask);

        //// 5. Show videos        
        imshow("Input Video", inputVideo);
        imshow("Result (Masked) Video", resultVideo);
        imshow("Mask", mask);
        
        waitKey(1);

}


void image_process::ImageCallback(const sensor_msgs::Image::ConstPtr &img){
 
        ROS_INFO("image(%d %d)", img->width, img->height);

        try{
                cv_ptr=cv_bridge::toCvCopy(img, sensor_msgs::image_encodings::BGR8);
				img_=cv_ptr->image.clone();
				image_tracking();
			
        } catch(cv_bridge::Exception &e){
                ROS_ERROR("error");
                return;
        }
}

int main(int argc, char **argv){

        ros::init(argc, argv, "main");
        ros::NodeHandle nh;

        image_transport::ImageTransport it(nh);
        image_process ob=image_process(&it);
    	
        ros::spin();

	  }

3. 라즈베리파이에서 uvc_camera 실행

4. 라즈베리파이 카메라 ros 설정 방법은 아래 링크의 유튜브를 참고했습니다.

https://youtu.be/9SYVtLhpLvQ

 

 


                                                                         Threshold(Hue 값조절)

 

 

                                              아래 그림을 기반으로 초록색만 검출되도록 값을 조절하겠습니다.

 

                                                                   트랙바를 이용하여 값을 조절해줍니다.

                                   위의 그래프 기준으로 Hue값을 60~180으로하니 아래와 같이 초록색을 잘 검출합니다.

                                                  그런데...... 역시나 파란색도 검출이됩니다..... ㅠㅠㅠ

                       그러면 트랙바로 여차여차해서 Hue:57~97로 바꾸어 줍니다.

                     편안쓰......

                  


                                                                                라벨링

 

https://www.youtube.com/watch?v=kOqUw7t5bYk&list=WL&index=5&t=150s 

 위의 유튜브를 참고하여 아래처럼 코드를 수정해줍니다.

void image_process::image_tracking(){
		Mat inputVideo;
		inputVideo=cv_ptr->image.clone();
	 	cv::Mat inputVideoHSV;
        cv::cvtColor(inputVideo, inputVideoHSV, cv::COLOR_BGR2HSV);

       
        Mat mask;
        // params: input array, lower boundary array, upper boundary array, output array
        inRange(
            inputVideoHSV, 
            cv::Scalar(minHue, minSat, minVal), 
            cv::Scalar(maxHue, maxSat, maxVal), 
            mask
        );
        Mat resultVideo;
        
        bitwise_and(inputVideo, inputVideo, resultVideo, mask);
		Mat ing_labels, stats, centroids;
		int numOfLabels=connectedComponentsWithStats(mask,img_labels, stats, centroids, 8, CV_32S);
		for (int j=1;j< numOfLabels; j++)
		{
			int area = stats.at<int>(j, CC_STAT_AREA);
			int left = stats.at<int>(j, CC_STAT_LEFT);
			int top = stats.at<int>(j, CC_STAT_TOP);
			int width = stats.at<int>(j, CC_STAT_WIDTH);
			int height = stats.at<int>(j, CC_STAT_HEIGHT);

			centerX = centroids.at<double>(j,0);
			centerY = centroids.at<double>(j,1);

			if (area >100)
			{
				circle(inputVideo, Point(centerX, centerY), 5, Scalar(255, 0, 0), 1);
				rectangle(inputVideo, Point(left, top), Point(left+width, top + height) , Scalar(0,0, 255), 1);

			}
		}
        //// 5. Show videos        
        imshow("Input Video", inputVideo);
        imshow("Result (Masked) Video", resultVideo);
        imshow("Mask", mask);

        //// Wait for 'esc' (27) key press for 30ms. If pressed, end program.
        waitKey(1);

}

고러면 아래와같은 결과가 나오게됩니다.