박민혀기

CELLON Kart Source Code 1.3.3v (2023.08.22) 본문

CELLON Kart(Tracking)/Source Code

CELLON Kart Source Code 1.3.3v (2023.08.22)

박민혀기 2023. 8. 22. 21:10

Update Feature

  • AdaptiveHSV balance(meanHSV & This_HSV) 7:3
  • Update meanHSV 10 frames

Next Develop

  • AutoFocus 카메라 사용시 샤프닝 적용
  • Stabilization
  • Size to HSV ratio

 

셋팅값은 무의미

ex) dis_HSV

#include <iostream>
#include <cmath>
#include <vector>
#include <opencv2/opencv.hpp>

#define COUNT_CONTOUR   5       //MIN_CONTOUR >= COUNT_CONTOUR

using namespace std;
using namespace cv;

Mat frame;
Scalar meanHSV = Scalar(0, 0, 0);
int  Adaptive_Cnt = 0;
bool comparePointVectors(const vector<Point>& a, const vector<Point>& b) {
        return a.size() > b.size();
}

vector<vector<Point>> SortingArea(vector<vector<Point>> SortingContours) {
        sort(SortingContours.begin(), SortingContours.end(), comparePointVectors);

        return SortingContours;
}

Scalar pixels_avg(vector<Scalar> pixels) {
        Scalar avgHSV(0, 0, 0);

        for (int i = 0; i < pixels.size(); i++)
                avgHSV += pixels[i];

        avgHSV /= static_cast<float>(pixels.size());
        return avgHSV;
}

int Close_HSV(vector<Scalar> Compare_HSV_List) {
        int Close_HSV_Index = 0;
        int Close_HSV_Dis, Close_HSV_Dis_List;
        Scalar Close_HSV = Compare_HSV_List[0];
        Scalar Close_HSV_Min, Close_HSV_Min_List, Close_HSV_List;

        for (int i = 1; i < Compare_HSV_List.size(); i++) {
                Close_HSV_Min = meanHSV - Close_HSV;
                Close_HSV_Dis = abs(Close_HSV_Min[0]) + abs(Close_HSV_Min[1]) + abs(Close_HSV_Min[2]);

                Close_HSV_Min_List = meanHSV - Compare_HSV_List[i];
                Close_HSV_Dis_List = abs(Close_HSV_Min_List[0]) + abs(Close_HSV_Min_List[1]) + abs(Close_HSV_Min_List[2]);

                if (Close_HSV_Dis > Close_HSV_Dis_List) {
                        Close_HSV = Compare_HSV_List[i];
                        Close_HSV_Index = i;
                }
                else    continue;
        }

        return Close_HSV_Index;
}

void AdaptiveHSVUpdate(vector<vector<Point>> Contours, int Close_Index) {
        Mat hsv_frame;
        cvtColor(frame, hsv_frame, COLOR_BGR2HSV);
        Mat contours_mask = Mat::zeros(frame.size(), CV_8UC1);
        drawContours(contours_mask, Contours, Close_Index, Scalar(255), -1);
//      imshow("contours_mask", contours_mask);

        vector<Scalar> pixels;
        for (int y = 0; y < contours_mask.rows; y++) {
                for (int x = 0; x < contours_mask.cols; x++) {
                        if (contours_mask.at<uchar>(y, x) == 255) {
                                pixels.push_back(hsv_frame.at<Vec3b>(y, x));
                        }
                }
        }

        Scalar This_HSV = pixels_avg(pixels);
//      meanHSV = (meanHSV + This_HSV) / 2;
//      meanHSV = (meanHSV * 70 + This_HSV * 30) / 100;

        cout << "This HSV : " << This_HSV << endl;
        cout << "mean HSV : " << meanHSV << endl;
        cout << "---dis HSV : " << abs(meanHSV[0] - This_HSV[0]) << ", " <<  abs(meanHSV[1] - This_HSV[1]) << ", "
                << abs(meanHSV[2] - This_HSV[2]) << "---" << endl;

}

void HSV_Process(Scalar lowerHSV, Scalar upperHSV, Size resol) {
        Mat hsv_frame, mask;
        vector<Scalar> HSV_List;

        cvtColor(frame, hsv_frame, COLOR_BGR2HSV);
        inRange(hsv_frame, lowerHSV, upperHSV, mask);
        //imshow("mask", mask);

        vector<vector<Point>> contours;
        findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
        contours = SortingArea(contours);

        cout << contours.size() << endl;
        if(contours.size() >= COUNT_CONTOUR){
                for (int i = 0; i < COUNT_CONTOUR; i++) {
                        Rect Max_BoundRect = boundingRect(contours[i]);
                        if (Max_BoundRect.width < resol.width / 10 || Max_BoundRect.height < resol.height / 10) continue;

                        Mat contours_mask = Mat::zeros(frame.size(), CV_8UC1);
                        drawContours(contours_mask, contours, i, Scalar(255), -1);

                        //mean으로 가능은 할 듯
                        vector<Scalar> pixels;
                        for (int y = 0; y < contours_mask.rows; y++) {
                                for (int x = 0; x < contours_mask.cols; x++) {
                                        if (contours_mask.at<uchar>(y, x) == 255) {
                                                pixels.push_back(hsv_frame.at<Vec3b>(y, x));
                                        }
                                }
                        }

                        HSV_List.push_back(pixels_avg(pixels));
                }
        }

        if (HSV_List.size() > 0) {
                int Close_Contour_Index = Close_HSV(HSV_List);
                Rect boundRect = boundingRect(contours[Close_Contour_Index]);
                //drawContours(frame, contours, Close_Contour_Index, cv::Scalar(0, 255, 255), 1);
                rectangle(frame, boundRect, Scalar(0, 255, 0), 2);

                Adaptive_Cnt++;
                if(Adaptive_Cnt >= 10){
                        AdaptiveHSVUpdate(contours, Close_Contour_Index);
                        Adaptive_Cnt = 0;
                }
        }
}

Scalar Push_Button(Rect2i roi_point) {
        Mat hsv_frame;
        hsv_frame = frame(roi_point).clone();
        cvtColor(hsv_frame, hsv_frame, COLOR_BGR2HSV);

        //imshow("hsv_frame", hsv_frame);

        return mean(hsv_frame);
}

int main() {
        VideoCapture cap = VideoCapture(0);
        if (!cap.isOpened()) {
                cout << "Could't load camera" << endl;
                return -1;
        }

        double width = cap.get(CAP_PROP_FRAME_WIDTH);
        double height = cap.get(CAP_PROP_FRAME_HEIGHT);
        width = 640;
        height = 480;
        cap.set(CAP_PROP_FRAME_WIDTH, width);
        cap.set(CAP_PROP_FRAME_HEIGHT, height);

        namedWindow("frame");

        int key;
        int frameCount = 0;
        bool Start_Flag = false;
        Scalar dis_HSV = Scalar(40, 40, 100);
        Scalar lowerHSV, upperHSV;
        Rect2i roi_frame = Rect(Point(width / 10 * 4, height / 10 * 5), Point(width / 10 * 6, height / 10 * 7));

        while (1) {
                cap >> frame;
                flip(frame, frame, 1);
                if (frame.empty()) {
                        cout << "Could't load frame" << endl;
                        return -1;
                }

                //Raspberry Camera Mode//
//Mat gaussian_blur;
//GaussianBlur(frame, gaussian_blur, Size(9, 9), 5);
//Mat sharpened = frame - gaussian_blur;
//Mat result = frame + sharpened;

                key = waitKey(10);
                if (key == 27)  break;
                else if (key == 32) {
                        meanHSV = Push_Button(roi_frame);
                        cout << "meanHSV : " << meanHSV << endl;

                        lowerHSV = meanHSV - dis_HSV;
                        upperHSV = meanHSV + dis_HSV;

                        Start_Flag = true;
                }

                if (Start_Flag) HSV_Process(lowerHSV, upperHSV, Size(width, height));

                rectangle(frame, roi_frame, Scalar(0, 0, 255), 2, 8);
                imshow("frame", frame);
        }

        cap.release();
        destroyAllWindows();

        return 0;
}