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