3、轮廓着色

轮廓着色


#include <iostream>
#include <vector>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include <opencv2/imgproc/types_c.h>

#include <opencv2/imgproc/imgproc_c.h>

#include <algorithm>

#define SHOW_TEMP 1;

using namespace std;
using namespace cv;





Point2f operator-(Point2f a, Point2f b)
{
	Point2f temp(0, 0);
	temp.x = a.x - b.x;
	temp.y = a.y - b.y;
	return temp;

}

Point2f operator+(Point2f a, Point2f b)
{
	Point2f temp(0, 0);
	temp.x = a.x + b.x;
	temp.y = a.y + b.y;
	return temp;

}


float operator*(Point2f a, Point2f b)
{
	float multiplicate = a.x * b.x + a.y * b.y;
	return multiplicate;
}




struct edgePoint {

	int         ind;
	cv::Point2f pos;
	float     angle;

public:
	edgePoint(const int& _ind, const cv::Point2f& _pos, const double& _angle) : ind(_ind),
		pos(_pos), angle(_angle)
	{

	}
	edgePoint() {}
};



bool cmp(edgePoint a, edgePoint b)
{
	return a.angle > b.angle;
};


double dis2(double x1, double y1, double x2, double y2) {
	return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
}
// 计算两点的坐标夹角,360度余弦值
double arccos(double x0, double y0, double x1, double y1)
{
	double angle = 0;
	double l = dis2(x0, y0, x1, y1);
	l = sqrt(l);
	if (y1 - y0 > 0) { angle = acos((x1 - x0) / l); }
	else { angle = 3.141592653 + 3.141592653 - acos((x1 - x0) / l); }
	//std::cout << (angle) << " ";
	return angle;
}//arccos

double arccos(cv::Point cneter, cv::Point p) {
	return arccos(double(cneter.x), double(cneter.y), double(p.x), double(p.y));
}

bool  isArcCurve(std::vector<cv::Point>& curve)
{
	bool isArc = false;

	cv::Point ps, pe, vec;
	ps = cv::Point(curve[0]);
	pe = cv::Point(curve[curve.size() - 1]);
	double angle0 = arccos(ps, pe);

	std::vector<double > rls;//左侧还是右侧
	for (int i = 1; i < curve.size() - 1; ++i) {
		double angle1 = arccos(ps, curve[i]);
		rls.push_back(angle1);
	}

	//若出现一次反转,则判定为否,以此保证曲线的单方向
	std::vector<bool >  rlbs;
	for (int i = 0; i < rls.size(); ++i) {
		bool isRight = false;
		if (rls[i] > angle0) {
			isRight = true;
		}
		else {
			isRight = false;
		}
		rlbs.push_back(isRight);
	}

	//若出现一次反转,则判定为否,以此保证曲线的单方向
	bool isSinVec = false;
	bool isRight = false;
	if (rlbs.size() > 0) {
		isRight = rlbs[0];
		for (int i = 1; i < rlbs.size(); ++i) {
			if (isRight != rlbs[i]) {
				isSinVec = true;
			}
		}
	}
	else {
	}

	isArc = isSinVec;
	return isArc;
}


int main() {



	// 读取图片,实际应用时该图片应从界面传入
	Mat imgSrc = imread("./8MS4.bmp");
	if (imgSrc.empty())
	{
		std::cout << "打开图片失败,请检查路径!!" << endl;
		return -1;
	}

	// 通过预处理,突出重点关注的线, 这部分的数字都可调整
	Mat imgGray;
	Mat imgGauss;
	Mat imgBin;
	cvtColor(imgSrc, imgGray, COLOR_BGR2GRAY);
	//GaussianBlur(imgGray, imgGauss, Size(5,5), 1.0);
	adaptiveThreshold(imgGray, imgBin, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 5, 5);
	imshow("adaptiveThreshold", imgBin);
	waitKey(3000);




	Mat imgDil;
	Mat imgEro;
	Mat kerneld;
	Mat kernele;
	kerneld = getStructuringElement(MORPH_RECT, Size(3, 3));
	dilate(imgBin, imgDil, kerneld);
	kernele = getStructuringElement(MORPH_RECT, Size(5, 5));
	erode(imgDil, imgEro, kernele);
	kernele = getStructuringElement(MORPH_RECT, Size(3, 1));
	erode(imgEro, imgEro, kernele);
	kerneld = getStructuringElement(MORPH_RECT, Size(3, 1));
	dilate(imgEro, imgEro, kerneld);
	// 预处理部分结束



	Mat dstImage = Mat::zeros(imgSrc.rows, imgSrc.cols, CV_8UC3);
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;

	findContours(imgEro, contours, hierarchy,
		CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

	int index = 0;
	for (; index >= 0; index = hierarchy[index][0])
	{

		Scalar color(rand() & 255, rand() & 255, rand() & 255);
		//drawContours(dstImage, contours, index, color, CV_FILLED, 8, hierarchy);
		drawContours(dstImage, contours, index, color, 1);
		if (isArcCurve(contours[index])) {
			Scalar color(rand() & 255, rand() & 255, rand() & 255);
			drawContours(dstImage, contours, index, color, CV_FILLED, 8, hierarchy);

		}

	}

	imshow("轮廓图", dstImage);

	waitKey(3000);


	// 显示图片,实际应用时不需要,可注释
	imshow("image", imgEro);
	waitKey(0);




	/*cout << "ok hello" << endl;*/

	//_CrtDumpMemoryLeaks();
	return 0;

}



运行图:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值