1. 程式人生 > >C++ Opencv——影象處理(預處理+矩形物體分割)

C++ Opencv——影象處理(預處理+矩形物體分割)

 影象預處理分割目標

// ROI提取
Mat Image_ROI(Mat frame)
{
	Mat gray, bw, img, bkup;
	/*目標提取——預處理——Mat ROI*/
	/*預處理很重要——直接找到目標*/
	//預處理很重要——直接找到目標
	// 灰度化
	cv::cvtColor(frame, gray, CV_BGR2GRAY);
	img = gray.clone();

	// 高斯濾波	
	cv::GaussianBlur(img, img, Size(5, 5), 0, 0);  //高斯濾波

	// 膨脹操作
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); //第一個引數MORPH_RECT表示矩形的卷積核,當然還可以選擇橢圓形的、交叉型的
	cv::dilate(img, img, element);  //實現過程中發現,適當的膨脹很重要

	//邊緣檢測
	cv::Canny(img, img, 30, 120, 3);   //邊緣提取
	//namedWindow("get contour", 1);
	//	cv::imshow("get contour", img);


	//從包好目標輪廓裡面找矩形的輪廓
	/**/
	bkup = gray.clone();
	Mat dstImg = frame.clone();
	//	cv::imshow("原圖", dstImg);//原圖
	/**/
	vector<vector<Point>> contours;
	vector<Vec4i> hierarcy;
	cv::findContours(img, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
	vector<Rect> boundRect(contours.size());
	vector<RotatedRect> box(contours.size());
	Point2f rect[4];
	Mat image_object;
	for (int i = 0; i < contours.size(); i++)
	{
		box[i] = minAreaRect(Mat(contours[i]));

		if (box[i].size.width < 100 || box[i].size.height < 100)//篩選
			continue;
		//rectangle(dstImg, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 255, 0), 2, 8);
		//circle(dstImg, Point(box[i].center.x, box[i].center.y), 5, Scalar(255, 255, 0), -1, 8);
		box[i].points(rect);
		/*for (int j = 0; j<4; j++)
		{
		line(dstImg, rect[j], rect[(j + 1) % 4], Scalar(255, 0, 255), 2, 8);
		}*/
		float angle;
		std::cout << "angle=" << box[i].angle << endl;
		angle = box[i].angle;
		char width[20], height[20];
		
		sprintf_s(width, "width=%0.2f", box[i].size.width);
		sprintf_s(height, "height=%0.2f", box[i].size.height);
		//putText(dstImg, width, Point(195, 260), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(255, 255, 0));
		//putText(dstImg, height, Point(190, 285), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(255, 255, 0));


		//利用仿射變換進行旋轉        另一種方法,透視變換
		if (0 < abs(angle) && abs(angle) <= 45)
			angle = angle;//負數,順時針旋轉
		else if (45 < abs(angle) && abs(angle) < 90)
			angle = 90 - abs(angle);//正數,逆時針旋轉
		Point2f center = box[i].center;  //定義旋轉中心座標
		double angle0 = angle;
		double scale = 1;
		Mat roateM = getRotationMatrix2D(center, angle0, scale);  //獲得旋轉矩陣,順時針為負,逆時針為正
		Mat roate_img;
		warpAffine(dstImg, roate_img, roateM, dstImg.size()); //仿射變換結果frame
		//	imshow("roateM", roate_img);

		/**/
		boundRect[i] = boundingRect(Mat(contours[i]));
		//顯示昉射後的目標區域圖
		int x0 = 0, y0 = 0, w0 = 0, h0 = 0;
		x0 = boundRect[i].x;
		y0 = boundRect[i].y;
		w0 = boundRect[i].width;
		h0 = boundRect[i].height;
		Mat ROI = roate_img(Rect(x0, y0, w0, h0));//擷取對應的區域
		//imshow("ROI", ROI);
		image_object = ROI;
		imwrite("測試ROI的準確性.jpg", ROI);
			
	}
	return image_object;
}