用容器存储影像中存在分支的线段

本文详细介绍了一种图像处理算法,该算法通过检测图像中的特征点来识别端点和交叉口,进而绘制出图像中的线条路径。算法首先读取图像并筛选出所有白色像素点,然后通过分析像素点的邻域确定端点和交叉口位置,最后通过连接这些关键点形成线条。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# include <stdio.h>
# include<iostream>
# include <opencv2/opencv.hpp>
# include<time.h>
#include <algorithm>
#include <string>
#include <vector>
#include<windows.h>
using namespace std;
using namespace cv;

typedef struct loc_and_degree
{
	CvPoint location;
	/*float distance;
	float degree;*/
	int flag = 0;
}l_and_d;

typedef struct i_o_s
{
	CvPoint location;
	int flag;
	int num_extreme_point = 0;
	int num_general_point = 0;
}info_of_site;


int main()
{
	Mat source = imread("11_14.png", 1);

	Mat draw(608, 608, CV_8UC3, Scalar(0, 0, 0));


	vector<CvPoint> all_white_pixes_in_image;//影像中所有白色点的位置
	CvPoint white_pixes_location;

	for (int i = 0; i < source.rows; i++)
	{
		Vec3b * ptr_color = source.ptr<Vec3b>(i);
		for (int j = 0; j < source.cols; j++)
		{
			int value = (*ptr_color)[0] + (*ptr_color)[1] + (*ptr_color)[2];
			if ((0 < value) && value <= 765)
			{
				white_pixes_location.x = j;
				white_pixes_location.y = i;
				all_white_pixes_in_image.push_back(white_pixes_location);
			}
			ptr_color++;
		}
	}
	vector<CvPoint> ::iterator start = all_white_pixes_in_image.begin(), end = all_white_pixes_in_image.end();
	for (start; start < end; start++)
	{
		circle(draw, *start, 0.5, Scalar(255, 255, 255), -1);//在图像中画出特征点,2是圆的半径
	}
	imshow("图像", draw);
	//waitKey();
	//通过八邻域找端点(extreme_point)
	int neighbourhood_x[] = { -1,-1,-1, 0,0, 1,1,1 };//竖向八邻域
	int neighbourhood_y[] = { -1, 0, 1,-1,1,-1,0,1 };
	vector<CvPoint> extreme_point;//存放端点库
	CvPoint extreme_point_location;//端点
	vector<CvPoint>::iterator start2 = all_white_pixes_in_image.begin(), end2 = all_white_pixes_in_image.end();
	for (start2; start2 < end2; start2++)
	{
		Vec3b color = 0;
		int value = 0;
		for (int k = 0; k < 8; k++)
		{
			color = draw.at<Vec3b>(start2->y + neighbourhood_y[k], start2->x + neighbourhood_x[k]);
			value += int(color[0] + color[1] + color[2]);
		}
		if (value == 765)//8邻域中只有1个白色像素点的位置为端点
		{
			extreme_point_location.x = start2->x;
			extreme_point_location.y = start2->y;
			extreme_point.push_back(extreme_point_location);
		}
	}

	//从2个端点,选择单个端点,并将直线存储
	CvPoint site1;
	vector<CvPoint> sites1;
	l_and_d point_sign;
	vector<l_and_d> line, line1, line2;
	for (auto &element : all_white_pixes_in_image)//初始化所有白点并将标志位初始化为0
	{
		point_sign.location = element;
		line1.push_back(point_sign);
	}

	for (auto &element : extreme_point)
	{
		for (int i = 0; i < line1.size(); i++)//将所有白点赋值为0并将端点初始化为1,存放于line1
		{
			if (line1[i].location.x == element.x && line1[i].location.y == element.y)
			{
				line1[i].flag = 1;
			}
		}
	}

	vector<CvPoint>flag_equal_2;
	Mat draw1 = draw.clone();
	line2 = line1;
	for (auto &element : line1)//将道路中的交叉口设为端点
	{
		if (element.flag == 0)
		{
			int count = 0;
			for (int i = 0; i < 8; i++)
			{
				CvPoint cross(element.location.x + neighbourhood_x[i], element.location.y + neighbourhood_y[i]);
				Vec3b color = draw.at<Vec3b>(cross.y, cross.x);
				int value = color[0] + color[1] + color[2];

				if (value == 765)
				{
					count++;

				}
				if (count > 2)
				{

					for (auto &element1 : line1)
					{
						if (element1.location.x == cross.x && element1.location.y == cross.y)
						{
							element1.flag = 1;
							flag_equal_2.push_back(cross);
							circle(draw1, cross, 0.5, Scalar(0, 0, 255), 1, 8, 0);
						}

					}
				}
			}
		}
	}

	imwrite("交叉口.png", draw1);
	line = line1;

	vector<info_of_site> all_pixes_attributes;
	for (auto &element : line)
	{
		info_of_site pixes_attributes;
		for (int i = 0; i < 8; i++)
		{
			CvPoint temp(element.location.x + neighbourhood_x[i], element.location.y + neighbourhood_y[i]);
			for (auto &element1 : line)
			{
				if (element1.location.x == temp.x && element1.location.y == temp.y)
				{
					pixes_attributes.num_general_point++;
					if (element1.flag == 1)
					{
						pixes_attributes.num_extreme_point++;
					}

					break;
				}

			}
		}
		pixes_attributes.flag = element.flag;
		pixes_attributes.location = element.location;
		all_pixes_attributes.push_back(pixes_attributes);
	}
	vector<vector<CvPoint>>final_line;//存放多组 线段点
									  /***********************************************************************************************************/
	for (auto &element5 : all_pixes_attributes)
	{

		while (element5.flag == 1)
		{
			vector<CvPoint>part_line;
			element5.flag = 3;
			part_line.push_back(element5.location);
			for (int i = 0; i < 8; i++)
			{
				CvPoint temp = CvPoint(element5.location.x + neighbourhood_x[i], element5.location.y + neighbourhood_y[i]);
				for (auto &element6 : all_pixes_attributes)
				{
					if (temp.x == element6.location.x && temp.y == element6.location.y && element6.flag == 0)
					{
						element6.flag = 3;
						part_line.push_back(temp);

						
						if (element6.num_extreme_point == 1)
						{
							for (int k = 0; k < 8; k++)
							{
								CvPoint temp11 = CvPoint(element6.location.x + neighbourhood_x[i], element6.location.y + neighbourhood_y[i]);
								for (auto &element7 : all_pixes_attributes)
								{
									if (temp11.x == element7.location.x && temp11.y == element7.location.y && element7.flag == 1)
										part_line.push_back(temp11);
								}
							}
						}


						element5.location = element6.location;
						i = 0;

						break;
					}
				}
			}
			
			
			final_line.push_back(part_line);
		}
	}
	/**************************************************************
	补充功能:将所有尺寸为1且坐标相邻的点进行合并 (待完善!!!!)
	**************************************************************/










	/**************************************************************
						去除相同的点位
	**************************************************************/
	
	vector<vector<CvPoint>> index;
	for (int j =0 ;j<final_line.size();j++)
	{
		vector<CvPoint> index1;
		for (int i = 0; i < final_line[j].size(); i++)
		{
			if (final_line[j].size() > 1)
			{
				if (i == 0 && (final_line[j][i].x != final_line[j][i + 1].x || final_line[j][i].y != final_line[j][i + 1].y))
				{
					index1.push_back(final_line[j][i]);
					index1.push_back(final_line[j][i + 1]);
				}
				else if (i > 0 && i < final_line[j].size() - 1 && (final_line[j][i].x != final_line[j][i + 1].x || final_line[j][i].y != final_line[j][i + 1].y))
				{
					index1.push_back(final_line[j][i + 1]);
				}
			}
			else if(final_line[j].size() == 1)
			{


				index1.push_back(final_line[j][i]);
				
				index.push_back(index1);
			}
			
		}
		index.push_back(index1);
	}

	
	










	/*****************************************************************************************************************/
	Mat  h(608, 608, CV_8UC3, Scalar(255, 255, 255));

	//Mat  h(9120, 14592, CV_8UC3, Scalar(255, 255, 255));
	vector<vector<CvPoint>>::iterator start9 = final_line.begin(), end9 = final_line.end();
	for (int i = 0; i < index.size(); i++)
	{
		for (int j = 0; j < index[i].size(); j++)
		{
			if (index[i].size()==0)
				continue;
			else
			{
			circle(h, index[i][j], 0.5, Scalar(0, 0, 0), -1);
			imshow("hh", h);
			waitKey(2);
			}

		}
	}
	imwrite("haha.png", h);
	waitKey();

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘟嘟love佳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值