opencv 截取任意四边形区域的图像

截取任意四边形区域的图像。

mask就是结果。

需要定义四边形区域,分别是 tl, tr, bl, br

 

std::map<int, std::set<int>> generateBorders(const std::vector<cv::Point> & vecPts)
{
	std::map<int, std::set<int>> borders;
	cv::Point tl(vecPts[0]), tr(vecPts[1]), bl(vecPts[2]), br(vecPts[3]);

	// tl to tr
	double K = double(tl.y-tr.y) / (tl.x - tr.x);
	for (int i = tl.x; i < tr.x; ++i)
		borders[i].insert(cvRound(-K*(tl.x - i) + tl.y));

	// tr to br
	if (tr.x != br.x)
	{
		K = double(tr.y - br.y) / (tr.x - br.x);
		for (int i = tr.x; i < br.x; ++i)
			borders[i].insert(cvRound(-K*(tr.x - i) + tr.y));
	}

	// br to bl
	K = double(br.y - bl.y) / (br.x - bl.x);
	for (int i = bl.x; i < br.x; ++i)
		borders[i].insert(cvRound(-K*(br.x - i) + br.y));

	// bl to tl
	if (bl.x != tl.x)
	{
		K = double(bl.y - tl.y) / (bl.x - tl.x);
		for (int i = tl.x; i < bl.x; ++i)
			borders[i].insert(cvRound(-K*(bl.x - i) + bl.y));
	}

	for (auto it = borders.begin(); it!=borders.end(); ++it)
	{
		if ((*it).second.size() == 2)
			continue;

		std::set<int> newone = { *(*it).second.begin(), *(--(*it).second.end())};
		(*it).second.swap(newone);
	}

#ifdef DEBUG_CODE
	cv::Mat disp = cv::imread("1111.PNG", CV_LOAD_IMAGE_COLOR);

	for (auto it = borders.begin(); it != borders.end(); ++it)
	{
		cv::circle(disp, cv::Point((*it).first, *(*it).second.begin()), 1, cv::Scalar(255, 255, 0), -1);
		cv::circle(disp, cv::Point((*it).first, *(--(*it).second.end())), 1, cv::Scalar(0, 255, 255), -1);

	}

	cv::circle(disp, tl, 2, cv::Scalar(0, 0, 255), -1);
	cv::circle(disp, tr, 2, cv::Scalar(0, 0, 255), -1);
	cv::circle(disp, bl, 2, cv::Scalar(0, 0, 255), -1);
	cv::circle(disp, br, 2, cv::Scalar(0, 0, 255), -1);
#endif // DEBUG_CODE



	return borders;
}

cv::Mat generateMask(const cv::Mat & src,
	const std::vector<cv::Point> & vecPts)
{
	cv::Mat mask = cv::Mat::zeros(src.size(), CV_8UC1);

	cv::Point tl(vecPts[0]), tr(vecPts[1]), bl(vecPts[2]), br(vecPts[3]);
	std::map<int, std::set<int>> borders = generateBorders(vecPts);

	int minX = std::min(tl.x, bl.x),
		maxX = std::max(tr.x, br.x),
		minY = std::min(tl.y, tr.y),
		maxY = std::max(bl.y, br.y);

	uchar minZ = std::min(src.at<uchar>(tl), src.at<uchar>(tr));
	minZ = std::min(minZ, src.at<uchar>(bl));
	minZ = std::min(minZ, src.at<uchar>(br));


	for (size_t j= minY; j<maxY; ++j)
	{
		const uchar* pS = src.ptr<uchar>(j);
		uchar* pM = mask.ptr<uchar>(j);

		for (size_t i = minX; i < maxX; ++i)
		{
			// in the region.
			if (*borders[i].begin() < j && j < *(++borders[i].begin()))
			{
				pM[i] = pS[i];
			}
		}
	}

	return mask;
	
}

  

 

posted @ 2018-09-26 22:04  路边的十元钱硬币  阅读(1977)  评论(0编辑  收藏  举报