Opencv 330 如何裁剪图片中大的目标?

main.cpp

cv::Mat CropImage(cv::Mat& src, cv::RotatedRect& rotatedRect);
cv::Mat MaxBoxSelectionRotatedRect(cv::Mat& src, cv::RotatedRect& ret);

int main()
{
#if 1
	cv::VideoCapture capture;
	cv::Mat rawData;
	cv::Mat ROI;
	cv::namedWindow("Show", cv::WINDOW_NORMAL);
	cv::namedWindow("ROI", cv::WINDOW_AUTOSIZE);
	capture.open(0);
	capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
#if 0
	capture.set(cv::CAP_PROP_FRAME_WIDTH, 3264);
	capture.set(cv::CAP_PROP_FRAME_HEIGHT, 2448);
#endif
	cv::RotatedRect rotatedRect;
	while (capture.isOpened())
	{
		capture >> rawData;
		if (rawData.empty()){break;}
		/******************************算法处理*******************************************/
#if 1
		if (cv::waitKey(1) == Esc)
		{
			cv::imwrite("640x480.jpg", rawData);
		}
		cv::Mat src = rawData.clone();
		src = MaxBoxSelectionRotatedRect(src, rotatedRect);
		ROI = CropImage(rawData, rotatedRect);
#else
		ROI = ImageColorMode(rawData, 3);
#endif
		
		
		/*********************************************************************************/
		cv::imshow("ROI", ROI);
		cv::imshow("Show", src);
		//退出循环
		if (cv::waitKey(1) == Esc)
		{
			cv::imwrite("640x480.jpg", rawData);
			break;
		}
	}
#else

#endif
	pause();
    return 0;
}

cv::Mat CropImage(cv::Mat& src,cv::RotatedRect& rotatedRect)
{
	//std::cout << rotatedRect.size.width << "x" << rotatedRect.size.height << std::endl;
	//定义框架边框边距像素大小以及参照物像素大小
	const int pixel = 10;
	const int defaultPixel = 5000000;

	//获取4个最小矩形四个顶点
	cv::Point2f pts[4];
	rotatedRect.points(pts);

	//获取最小矩形中心点
	cv::Point2f center = cv::Point2f((pts[0].x + pts[2].x) / 2, (pts[0].y + pts[2].y) / 2);
	//获取旋转角度
	double angle = rotatedRect.angle;

	std::cout << "angle:" << angle << std::endl;
#if 0
	//获取最小矩形长和宽 获取该参数可实现长方形矩形始终水平放置
	int lineWidth = sqrt((pts[1].y - pts[0].y)*(pts[1].y - pts[0].y) + (pts[1].x - pts[0].x)*(pts[1].x - pts[0].x));
	int lineHeight = sqrt((pts[3].y - pts[0].y)*(pts[3].y - pts[0].y) + (pts[3].x - pts[0].x)*(pts[3].x - pts[0].x));
#endif
	
	//
	cv::Rect roi;
	//边距
	int margin = pixel * src.cols * src.rows / defaultPixel;
	//宽
	roi.width = rotatedRect.size.width - margin * 2;
	//高
	roi.height = rotatedRect.size.height - margin * 2;
	//矩形起始坐标
	roi.x = center.x - roi.width / 2;
	roi.y = center.y - roi.height / 2;

	//目标框选超出范围部分像素直接砍掉
	if (roi.x < 0) roi.x = 0;
	if (roi.y < 0) roi.y = 0;
	if (roi.x + roi.width > src.cols)
	{
		roi.width = src.cols - roi.x;
	}
	if (roi.y + roi.height > src.rows)
	{
		roi.height = src.rows - roi.y;
	}

	cv::Mat dst(src.rows, src.cols, CV_8UC3, cv::Scalar(0, 0, 0));
	//获取仿射矩阵 M
	cv::Mat matrix2D = cv::getRotationMatrix2D(center, angle, 1);
	//变换图像
	cv::warpAffine(src, dst, matrix2D, cv::Size(src.cols, src.rows));

	//ROI 最终结果
	cv::Mat ret(dst,roi);
#if 0
	cv::namedWindow("Return");
	cv::imshow("Return",ret);
#endif
	return ret;
}
cv::Mat MaxBoxSelectionRotatedRect(cv::Mat& src, cv::RotatedRect& ret)
{
	cv::Mat dst = src.clone();
	//颜色模型转换
	cv::cvtColor(src, src, cv::COLOR_BGR2HSV_FULL);
	//cv::Mat 向量容器
	std::vector<cv::Mat> threeChannels;
	//分割HSV模型,提取 V(亮度) 通道
	cv::split(src, threeChannels);
	cv::threshold(threeChannels.back(), src, 0, 255, cv::THRESH_OTSU);
	std::vector<std::vector<cv::Point>> contours;
	cv::findContours(src, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
	//假设最大轮廓值向量容器索引
	size_t maxContoursIndex = contours.size() - 1;
	//遍历向量容器
	for (size_t i = maxContoursIndex; i > 0; i--)
	{
		//寻找最大点集
		//if (contours.at(i).size() > contours.at(maxContoursIndex).size())
		//寻找最大的轮廓
		if (cv::contourArea(contours.at(i)) > cv::contourArea(contours.at(maxContoursIndex)))
		{
			//最大轮廓在向量容器中的位置
			maxContoursIndex = i;
		}
	}

	//std::cout << "contourAreaMax:" << cv::contourArea(contours.at(maxContoursIndex)) << std::endl;
	if (cv::contourArea(contours.at(maxContoursIndex)) < 488.0)//double minAreaRectSize = 488;
	{
		return dst;
	}

	ret = cv::minAreaRect(contours.at(maxContoursIndex));

	const int pixel = 10;
	const int defaultPixel = 5000000;
	int lineWidth = 2 * (dst.cols * dst.rows / 5000000);
	cv::Point2f pts[4];
	ret.points(pts);
#if 1
	//绘制最小外接矩形
	for (int i = 0; i < 4; ++i) {
		line(dst, pts[i], pts[(i + 1) % 4], cv::Scalar(0, 255, 0), lineWidth);
	}
#else
	roi = dst(cv::boundingRect(contours.at(maxContoursIndex)));
	//绘制最大外接矩形
	cv::rectangle(dst, cv::boundingRect(contours.at(maxContoursIndex)), cv::Scalar(0, 255, 0), 2, 8);
#endif
	return dst;
}
原文地址:https://www.cnblogs.com/cheungxiongwei/p/8303325.html