OpenCv-C++-小案例实战-切边(一)

假如说现在有这么一张图片如下:
在这里插入图片描述
现在我想要去掉这张图外面的白色区域,只留下红色线框以内的部分。最终效果如图所示:
在这里插入图片描述

那么对于这样一张图片,解决思路如下:
1、边缘检测
2、轮廓发现
3、求最小外接矩形
4、ROI截取

放上代码:

#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>

using namespace cv;
using namespace std;

Mat src, dst, gray_src;

int current_level = 50;
int max_level = 255;
void cut_image(int, void*);

const char* output_title = "rectminArea";
int main(int argc, char**argv)
{
	src = imread("D:/test/切边测试图.png", 1);
	if (src.empty())
	{
		cout << "图片未找到" << endl;
		return -1;
	}
	
	
	namedWindow(output_title,CV_WINDOW_AUTOSIZE);
	createTrackbar("Value", output_title, &current_level, max_level, cut_image);
	cut_image(0,0);
	imshow("input image", src);
	waitKey(0);
	return 0;

}
void cut_image(int, void*)
{
	Mat canyImg;
	cvtColor(src, gray_src, CV_BGR2GRAY);
	Canny(gray_src, canyImg, current_level, 2 * current_level, 3,false);

	vector<vector<Point>> contours;
	vector<Vec4i>hierachy;
	Mat showImg = Mat::zeros(src.size(), CV_8UC3);
	findContours(canyImg, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
	
	RNG rng(12345);

	int minw = src.cols*0.75;
	int minh = src.rows*0.75;

	Rect box; //获取roi区域
	Mat contoursimg= Mat::zeros(src.size(), CV_8UC3);
	for (size_t t = 0; t < contours.size(); t++)
	{
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		
		drawContours(contoursimg, contours, int(t), color, 1, 8, hierachy, 0, Point(0, 0));
		
		RotatedRect minrect = minAreaRect(contours[t]); //获取轮廓的最小外接矩形
		float angle = abs(minrect.angle);
		if (minrect.size.height > minh && minrect.size.width > minw && minrect.size.width < (src.cols - 5))
		{
			Point2f pts[4];
			minrect.points(pts); //获取最小外接矩形的四个顶点坐标
			for(int i=0;i<4;i++)
			{
				line(showImg,pts[i], pts[(i + 1) % 4], color, 2, 8, 0);
				cout << "X坐标:" << minrect.center.x <<" "<< "Y坐标:" << minrect.center.y << " "<<"偏移角度:" << angle << endl;
			}
			box = minrect.boundingRect();
		}
		
		if (box.width > 0 && box.height > 0)
		{
			Mat roiImg=src(box);//截取roi区域
			imshow("roiImg", roiImg);
		}
		
	}
	
	imshow(output_title, showImg);
	imshow("contours image", contoursimg);
	

}

所以,最终结果为:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
因为该图片旋转角度为0,也就是说,它是一个完完全全的正的矩形,如果,它是一个旋转一定角度后的图片该怎么做呢?下一篇文章记录。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
OpenCV小项目 这是一个个人在使用OpenCV过程中写的一些小项目,以及一些非常有用的OpenCV代码,有些代码是对某论文中的部分实现。 注意:代码是在Xcode里写的,如果要在win下测试,遇到问题自己修改。 opencv-rootsift-py 用python和OpenCV写的一个rootsift实现,其中RootSIFT部分的代码参照Implementing RootSIFT in Python and OpenCV这篇文章所写,通过这个你可以了解Three things everyone should know to improve object retrieval这篇文章中RootSIFT是怎么实现的。 sift(asift)-match-with-ransac-cpp 用C++OpenCV写的一个图像匹配实现,里面包含了采用1NN匹配可视化、1NN匹配后经RANSAC剔除错配点可视化、1NN/2NN<0.8匹配可视化、1NN/2NN<0.8经 RANSAC剔除错配点可视化四个过程,其中1NN/2NN<0.8匹配过程是Lowe的Raw feature match,具体可以阅读Lowe的Distinctive image features from scale-invariant keypoints这篇文章。这个对图像检索重排非常有用。另外里面还有用OpenCV写的ASIFT,这部分来源于OPENCV ASIFT C++ IMPLEMENTATION,ASIFT还可以到官网页面下载,ASIFT提取的关键点 比SIFT要多得多,速度非常慢,不推荐在对要求实时性的应用中使用。 更多详细的分析可以阅读博文SIFT(ASIFT) Matching with RANSAC。 有用链接 OpenCV3.0文档 // 测试sparse unsigned int centersNum = 10; vector descrNums; descrNums.push_back(8); descrNums.push_back(12); //unsigned int T[] = {1, 2, 1, 3, 2, 5, 4, 3, 10, 5; 4, 2, 6, 5, 2, 5, 4, 6, 2, 4}; unsigned int T[] = {1, 2, 1, 3, 2, 5, 4, 3, 10, 5, 4, 2, 6, 5, 2, 5, 4, 6, 2, 4}; sp_mat Hist(descrNums.size(), centersNum); static long int count = 0; for (int i = 0; i < descrNums.size(); i++){ unsigned int* desrcElementsTmp = new unsigned int[descrNums[i]]; memcpy(desrcElementsTmp, T + count, descrNums[i] * sizeof(T[0])); //cout << desrcElementsTmp[0] << '\t' << desrcElementsTmp[1] << '\t' << desrcElementsTmp[2] << '\t' << desrcElementsTmp[3] << '\t' << desrcElementsTmp[4] << '\t' <<endl; //cout << desrcElementsTmp[5] << '\t' << desrcElementsTmp[6] << '\t' << desrcElementsTmp[7] << '\t' << desrcElementsTmp[8] << '\t' << desrcElementsTmp[9] << '\t' << desrcElementsTmp[10] << '\t' <<endl; //cout << endl; sp_mat X(1, centersNum); X.zeros(); for (int j = 0; j < descrNums[i]; j++){ X(0, desrcElementsTmp[j]-1) += 1; } X.print("X:"); X = X/norm(X, 2); Hist.row(i) = X; count = count + descrNums[i]; delete desrcElementsTmp; } //Hist.print("Hist:");
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值