Programming/OpenCV

[OpenCV] 동영상 재생 + 프레임 측정 + 적응적 이진화 + 캐니에지 + 컨투어링 + 모멘트 + putText

꾸준희 2018. 10. 22. 16:05
728x90
반응형



동영상 재생 후 

프레임을 측정하고

적응적 이진화를 통해 이진화를 수행한다.



그 다음, 캐니 에지로 엣지를 따고나서 

컨투어링을 수행하여 탐지된 객체의 가장자리를 그리고, 컨투어링을 통해 면적을 계산한다. 



다음으로, 

객체를 둘러 쌓는 바운딩 박스(Bounding Box)를 통해 객체의 Width, Height를 구하는 예제이다. 


마지막으로 계산한 면적, 너비, 높이를 putText를 통해 화면에 표시한다. 






#include <stdio.h>
#include <time.h>
#include "opencv2\opencv.hpp"

using namespace cv;
using namespace std;

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

	Mat matOrg;
	Mat matOut;

	long totalFrames = 0;
	clock_t prevClock;
	int key = 0;

	VideoCapture cap("C:/Users/seohee/Desktop/pore video/test.avi");

	if (!cap.isOpened())
	{
		printf("video not opened");
		return -1;
	}

	prevClock = clock();

	while (key != 27) {

		cap >> matOrg;

		if (matOrg.empty()) {
			printf("video frame end\n");
			return -1;
		}

		cvtColor(matOrg, matOrg, CV_BGR2GRAY);

		clock_t curClock = clock();
		printf("%.2lf fps\n", (float)CLOCKS_PER_SEC / (float)(curClock - prevClock));
		prevClock = curClock;


		/* Variable */
		Mat frame;
		Mat binary;
		Mat canny;
		Mat result;

		double boundX = 0, boundY = 0;
		double area = 0.0;


		/* Frame Clone, Resizing */
		frame = matOrg.clone();
		resize(frame, frame, Size(), 0.8, 0.8);

		/* Adaptive Binarization */
		adaptiveThreshold(frame, binary, 255, 
                ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 21, 20);


		/* Canny, Contour, Drawing Contour */
		Canny(binary, canny, 100, 200, 3);

		vector<vector<cv::point>> contours;
		findContours(canny, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

		cvtColor(frame, result, CV_GRAY2BGR);
		drawContours(result, contours, -1, Scalar(0, 255, 250), 1);


		/* Calculate Pore point */
		// Get the moments
		vector<moments>mu(contours.size());

		for (int i = 0; i < contours.size(); i++)
			mu[i] = moments(contours[i], false);

		// Get the centroid of figures
		vector<point2d> mc(contours.size());
		for (int i = 0; i < contours.size(); i++)
			mc[i] = Point2d(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);


		/* Bounding box */
		vector<rect> boundRect(contours.size());
		vector<vector<point>>contours_poly(contours.size());

		for (int i = 0; i < contours.size(); i++)
		{
			approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
			boundRect[i] = boundingRect(Mat(contours_poly[i]));
		}


		/* Calculate Pore Area, Width, Height */
		/* Drawing Circle, Rectangle, putText */

		for (int i = 0; i < contours.size(); i++)
		{
			area = contourArea(contours[i]);
			boundX = boundRect[i].width;
			boundY = boundRect[i].height;

			if (area > 3) {

				circle(result, mc[i], 1.5, Scalar(0, 0, 255), -1, 8, 0);
				rectangle(result, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 0, 0), 1, 8, 0);

				Point p = mc[i];
				p.x += 3; p.y += 3;
				char buf1[100];
				sprintf_s(buf1, "A:%.1f W:%.1f H:%.1f", area, boundX, boundY);
				putText(result, buf1, p, CV_FONT_HERSHEY_SIMPLEX, 0.4, Scalar(255, 0, 0), 1, 1);

			}
		}

		imshow("Area, Width, Height", result);


		key = waitKey(1);
	}

	destroyAllWindows();

}








728x90
반응형