박민혀기
CELLON Kart Source Code 1.3.5v(YCrCb_ROI) (2023.08.30) 본문
CELLON Kart(Tracking)/Source Code
CELLON Kart Source Code 1.3.5v(YCrCb_ROI) (2023.08.30)
박민혀기 2023. 8. 30. 22:46Update Feature
- HSV Model -> YCrCb Model
- StaticROI -> CustomROI
Next Develop
- AutoFocus 카메라 사용시 샤프닝 적용 -> 적용 반응 미미
- Stabilization
- Size to HSV ratio
#include <iostream>
#include <cmath>
#include <vector>
#include <opencv2/opencv.hpp>
#define COUNT_CONTOUR 3 //MIN_CONTOUR >= COUNT_CONTOUR
using namespace std;
using namespace cv;
Mat frame, ycc_frame;
Scalar meanYCC = 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 avgYCC(0, 0, 0);
for (int i = 0; i < pixels.size(); i++)
avgYCC += pixels[i];
avgYCC /= static_cast<float>(pixels.size());
return avgYCC;
}
int Close_YCC_Pro(vector<Scalar> Compare_YCC_List) {
int Close_YCC_Index = 0;
int Close_YCC_Dis, Close_YCC_Dis_List;
Scalar Close_YCC = Compare_YCC_List[0];
Scalar Close_YCC_Min, Close_YCC_Min_List, Close_YCC_List;
for (int i = 1; i < Compare_YCC_List.size(); i++) {
Close_YCC_Min = meanYCC - Close_YCC;
Close_YCC_Dis = abs(Close_YCC_Min[0]) + abs(Close_YCC_Min[1]) + abs(Close_YCC_Min[2]);
Close_YCC_Min_List = meanYCC - Compare_YCC_List[i];
Close_YCC_Dis_List = abs(Close_YCC_Min_List[0]) + abs(Close_YCC_Min_List[1]) + abs(Close_YCC_Min_List[2]);
if (Close_YCC_Dis > Close_YCC_Dis_List) {
Close_YCC = Compare_YCC_List[i];
Close_YCC_Index = i;
}
else continue;
}
return Close_YCC_Index;
}
void AdaptiveYCCUpdate(vector<vector<Point>> Contours, int Close_Index) {
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(ycc_frame.at<Vec3b>(y, x));
}
}
}
Scalar This_YCC = pixels_avg(pixels);
// meanYCC = (meanYCC + This_YCC) / 2;
meanYCC = (meanYCC * 80 + This_YCC * 20) / 100;
// cout << "This YCC : " << This_YCC << endl;
// cout << "mean YCC : " << meanYCC << endl;
}
void YCC_Process(Scalar lowerYCC, Scalar upperYCC, Size resol) {
Mat mask;
vector<Scalar> YCC_List;
inRange(ycc_frame, lowerYCC, upperYCC, mask);
vector<vector<Point>> contours;
findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
contours = SortingArea(contours);
imshow("mask", mask);
// 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 / 20 || Max_BoundRect.height < resol.height / 20) 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(ycc_frame.at<Vec3b>(y, x));
}
}
}
YCC_List.push_back(pixels_avg(pixels));
}
}
if (YCC_List.size() > 0) {
int Close_Contour_Index = Close_YCC_Pro(YCC_List);
Rect boundRect = boundingRect(contours[Close_Contour_Index]);
rectangle(frame, boundRect, Scalar(0, 255, 0), 2);
Adaptive_Cnt++;
if(Adaptive_Cnt >= 5){
AdaptiveYCCUpdate(contours, Close_Contour_Index);
Adaptive_Cnt = 0;
}
}
}
Scalar Push_Button(Rect2i roi_point) {
Mat roi_ycc_frame;
roi_ycc_frame = frame(roi_point).clone();
cvtColor(roi_ycc_frame, roi_ycc_frame, COLOR_BGR2YCrCb);
return mean(roi_ycc_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_YCC = Scalar(20, 10, 10);
Scalar lowerYCC, upperYCC;
Rect2i roi_frame; //= Rect(Point(width / 10 * 4, height / 10 * 5), Point(width / 10 * 5, height / 10 * 6));
Mat Y2C_frame;
while (1) {
cap >> frame;
flip(frame, frame, 1);
if (frame.empty()) {
cout << "Could't load frame" << endl;
return -1;
}
key = waitKey(1);
if (key == 27) break;
else if (key == 32) {
roi_frame = selectROI(frame, false);
meanYCC = Push_Button(roi_frame);
lowerYCC = meanYCC - dis_YCC;
upperYCC = meanYCC + dis_YCC;
Start_Flag = true;
}
if (Start_Flag){
cvtColor(frame, ycc_frame, COLOR_BGR2YCrCb);
YCC_Process(lowerYCC, upperYCC, Size(width, height));
rectangle(frame, roi_frame, Scalar(0, 0, 255), 2, 8);
}
// rectangle(frame, roi_frame, Scalar(0, 0, 255), 2, 8);
imshow("frame", frame);
}
cap.release();
destroyAllWindows();
return 0;
}
'CELLON Kart(Tracking) > Source Code' 카테고리의 다른 글
CELLON Kart Source Code 1.3.6v(Size, HSV Ratio) (2023.08.31) (0) | 2023.08.31 |
---|---|
CELLON Kart Source Code(Tracker CSRT) (2023.08.30) (0) | 2023.08.30 |
CELLON Kart Source Code 1.3.4v(YCrCb) (2023.08.28) (0) | 2023.08.22 |
CELLON Kart Source Code 1.3.3v (2023.08.22) (0) | 2023.08.22 |
CELLON Kart Source Code 1.3.2V (2023.08.02) (0) | 2023.08.02 |