• 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;
    	
    }
    

      

  • 相关阅读:
    【2019-12-13】泛型
    【2019-12-12】函数
    【2019-12-10】类
    【2019-12-05】接口
    【2019-12-3】变量声明
    【2019-11-24】基础类型
    【2019-11-20】服务与DI简介
    【2019-11-20】组件简介
    android之ListView与Adapter(结合JavaBean)
    android基类Adapter
  • 原文地址:https://www.cnblogs.com/alexYuin/p/9710052.html
Copyright © 2020-2023  润新知