ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Day12
    교육/서울 ICT 이노베이션 고오급 시각과정 2021. 7. 2. 17:49
    728x90

    강분류기(Strong Classifier)

    비교적 정확한 분류기

    최종적으로 설계해야하는 분류기

    약분류기(weak Classifier)

    비교적 부정확한 분류기

    이진 분류의 경우 일반적으로 정확도는 무조건 50%이상

     

    앙상블 이론

    약분류기를 여러 개 조합한 것

    weighted vote방법을 사용해서 정확도가 높은건 가중치를 높게 쳐줘서 선형적으로 만들어줌

    ex)decision tree, random forest, AdaBoost

    1. Random Forest
      • decision tree의 샘플 n개가 있으면 이 중에서 랜덤으로 n-d개 골라서 독립적으로 decision tree를 여러개 만들어서 합치는 것
      • 각각의 decision tree마다 성능을 측정할 수 있으므로 random forest는 특징별로 중요도가 나오게 됨
      • 오버피팅을 줄이고 robust한 특징을 만듦(≒dropout)
    2. AdaBoost
      • 전체 동작 과정
        1. 한정된 수의 약분류기를 정의
        2. 모든 샘플에 대해 모든 약분류기를 테스트
        3. 가장 강한 분류기를 분류기 모음에 추가
          • 가장 좋은 분류를 하나 고르고 나면 다음 분류기는 이전 분류기가 실패한 샘플에 대해 가중치를 높게 줘서 이전 분류기가 실패한 샘플을 잘 분류한 분류기를 선택, 각 분류기가 독립적
        4. 분류기 모음을 이용하여 강분류기를 만들고 성능 측정
        5. 만족스러운 성능이 나오지 않으면 2로 돌아감

    Viola Jones Object Detector Framework : Adaboost를 이용해 만든 detector, 실시간 물체 검출 알고리즘

    1. Sliding Window방식
      • 모든 영역에 대해 classification하면 detect하게 됨
      • viola-jones의 경우 가변크기/고정비율(주로 정사각형)
    2. Haar-like Feature 
      • 특정 영역의 밝기차를 표현
      • 사람을 검출할때 사용
    3. Integral Image
      • Haar-Like Feature을 뽑아낼 때 빨리 계산하기 위해 사용(위의 그림에서 왼쪽 사각형의 점 1,2,3,4)
    4. AdaBoost
    5. Cascade Architecture
      • Sliding Window할 때 window가 모든 강분류기(Adaboost로 만들어진 약분류기 집합)를 통과해야 특징으로 추출, 중간에 하나라도 통과 못 하면 다음 window보는 식으로 해서 빠르게 동작가능
      • 약분류기가 필터의 역할을 하는데 accuracy기준X recall기준O(얼굴O/X의 기준이 중간이 아니라 완전 얼굴X만 아니면 다 통과)

    2. 캐스케이드 분류기와 얼굴 검출

    void detectAndDisplay(Mat frame)
    {
    	Mat frame_gray;
    	cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
    	equalizeHist(frame_gray, frame_gray);
    	//-- Detect faces
    	std::vector<Rect> faces;
    	face_cascade.detectMultiScale(frame_gray, faces);
    	for (size_t i = 0; i < faces.size(); i++)
    	{
    		Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
    		ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 4);
    		Mat faceROI = frame_gray(faces[i]);	//얼굴 영역만 자른 거
    		//-- In each face, detect eyes
    		std::vector<Rect> eyes;
    		eyes_cascade.detectMultiScale(faceROI, eyes);
    		for (size_t j = 0; j < eyes.size(); j++)
    		{
    			Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
    			int radius = cvRound((eyes[j].width + eyes[j].height) * 0.25);
    			circle(frame, eye_center, radius, Scalar(255, 0, 0), 4);
    		}
    	}
    	//-- Show what you got
    	imshow("Capture - Face detection", frame);
    }

    3. HOG 알고리즘과 보행자 검출

    HOG(Histograms of Oriented Gradients)

    파라미터가 많음 ex)이미지 크기, 셀의 크기,...

    이미지의 크기가 고정되어 있어서 다양한 이미지에 적용하려면 피라미드형태로 HOG를 새로 뽑고 해야함

    HOG를 통해 특정한 영역에 대해 벡터가 나오게 되면 SVM을 이용해서 계산

    주로 보행자 검출에 사용됨

    //opencv에서 HOGDescriptor가 제공해줌
    HOGDescriptor hog;
    hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());

    4. QR 코드 검출

    //QRCode검출하는 함수도 제공
    QRCodeDetector detector;
    //QR Code의 코너점이 출력됨

     

     

    머신러닝

    1. 서포트 벡터 머신(SVM)

    SVM의 파라미터 : 이상치를 무시하는 파라미터, 직선이 아닌 곡선으로 분할할 수 있게 자유도를 조절하는 파라미터

    //사용자가 숫자를 쓰면 1-9중 어떤 숫자를 썼는지 판별해주는 코드
    #include <opencv2/opencv.hpp>
    
    using namespace cv;
    using namespace cv::ml;
    using namespace std;
    
    Mat normalize(Mat src)
    {
    	//일반 이미지에 boundingRect를 사용하면 0이 아닌 부분을 사각형으로 검출, 이걸로 이미지 사이즈 정규화
    	Rect rect = boundingRect(src);	
    	Mat dst;
    	//resize(src(rect), dst, Size(32, 32), 0, 0, INTER_AREA);
    	resize(src, dst, Size(32, 32), 0, 0, INTER_AREA);
    	return dst;
    }
    
    //Ptr : 스마트 포인터 자료형 SVM은 항상 이 자료형으로 return해줘야함
    Ptr<SVM> train_hog_svm(const HOGDescriptor& hog)
    {
    	Mat digits = imread("images/digits.png", IMREAD_GRAYSCALE);
    	Mat train_hog, train_labels;
    
    	//훈련시킬 이미지가 50행 100열이라서 잘라주는 코드
    	for (int j = 0; j < 50; j++)
    	{
    		for (int i = 0; i < 100; i++)
    		{
    			Mat crop = digits(Rect(i * 20, j * 20, 20, 20));
    			Mat resized = normalize(crop);
    
    			vector<float> desc;
    			hog.compute(resized, desc);
    
    			Mat desc_mat(desc);
    			train_hog.push_back(desc_mat.t());	//x
    			train_labels.push_back(j / 5);		//y
    		}
    	}
    
    	Ptr<SVM> svm = SVM::create();
    	svm->setType(SVM::Types::C_SVC);
    	svm->setKernel(SVM::KernelTypes::RBF);
    	svm->setC(2.5);
    	svm->setGamma(0.50625);
    	svm->train(train_hog, ROW_SAMPLE, train_labels);
    
    	return svm;
    }
    
    Point ptPrev(-1, -1);
    void on_mouse(int event, int x, int y, int flags, void* userdata)
    {
    	Mat img = *(Mat*)userdata;
    
    	if (event == EVENT_LBUTTONDOWN)
    	{
    		ptPrev = Point(x, y);
    	}
    	else if (event == EVENT_LBUTTONUP)
    	{
    		ptPrev = Point(-1, -1);
    	}
    	else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
    	{
    		line(img, ptPrev, Point(x, y), Scalar::all(255), 40, LINE_AA, 0);
    		ptPrev = Point(x, y);
    		imshow("img", img);
    	}
    }
    
    int ch15()
    {
    	//SVM 훈련시키는 코드
    	HOGDescriptor hog(Size(32, 32), Size(16, 16), Size(8, 8), Size(8, 8), 9);
    
    	struct stat buffer;
    	Ptr<SVM> svm;
    	if (stat("output.xml", &buffer) == 0)
    	{
    		printf("load saved model...\n");
    		svm = SVM::load("output.xml");
    		printf("done.\n");
    	}
    	else
    	{
    		printf("train model...\n");
    		svm = train_hog_svm(hog);
    		printf("done.\n");
    	}
    	
    	//화면에 숫자를 그리는 코드
    	Mat img = Mat::zeros(400, 400, CV_8U);
    
    	imshow("img", img);
    	setMouseCallback("img", on_mouse, (void*)&img);
    
    	while (true)
    	{
    		int c = waitKey(0);
    
    		if (c == ' ')
    		{
    			Mat img_resize = normalize(img);
    
    			vector<float> desc;
    			hog.compute(img_resize, desc);
    
    			Mat desc_mat(desc);
    			int res = cvRound(svm->predict(desc_mat.t()));
    			cout << res << endl;
    			img.setTo(0);
    			imshow("img", img);
    			imshow("img_resize", img_resize);
    		}
    		else if (c == 's')
    		{
    			printf("save model.. \n");
    			svm->save("output.xml");
    			printf("done.\n");
    		}
    		else if (c == 'q')
    		{
    			break;
    		}	
    	}
    	return 0;
    }
    
    void main()
    {
    	ch15();
    }

     

    '교육 > 서울 ICT 이노베이션 고오급 시각과정' 카테고리의 다른 글

    day14  (0) 2021.09.01
    Day13  (0) 2021.09.01
    Day11  (0) 2021.06.30
    Day10  (0) 2021.06.17
    Day9  (0) 2021.06.16

    댓글

Designed by Tistory.