明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2147|回复: 14

[求助] 请教各位大佬:如何求最右边的所有点

[复制链接]
发表于 2022-5-27 21:56:25 | 显示全部楼层 |阅读模式
本帖最后由 随便的C# 于 2022-5-27 21:57 编辑

比如图上有好几列点,我想获得最右边的所有点,例如方框里的点。
大佬们能给个解题思路吗?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2022-5-31 15:55:33 | 显示全部楼层
本帖最后由 landsat99 于 2022-5-31 17:07 编辑

响应大佬,也来一段代码,,   Canopy算法的,也算一种簇类分析定质心。

Github https://github.com/AlanConstantine/CanopyByPython

修改: 添加了核心参数T1,T2的粗略判断。取为整体矩阵 Data[:,0] 最大值和最小值区间的比例参数。
用楼上大咖的点位数据 再次试算。

  1. # -*- coding: utf-8 -*-
  2. # @Title:       Algorithm.Canopy :: Class.Canopy.py
  3. # @From:        https://github.com/AlanConstantine/CanopyByPython
  4. # @Date:        2022.05.31

  5. import math
  6. import random
  7. import numpy as np
  8. from datetime import datetime
  9. from pprint import pprint as p
  10. import matplotlib.pyplot as plt


  11. class Canopy:

  12.     def __init__(self, dataset):
  13.         self.dataset = dataset
  14.         self.t1 = 0
  15.         self.t2 = 0

  16.     # 设置初始阈值
  17.     def setThreshold(self, t1, t2):
  18.         if t1 > t2:
  19.             self.t1 = t1
  20.             self.t2 = t2
  21.         else:
  22.             print('t1 needs to be larger than t2!')

  23.     # 使用欧式距离进行距离的计算
  24.     def euclideanDistance(self, vec1, vec2):
  25.         return math.sqrt(((vec1 - vec2)**2).sum())

  26.     # 根据当前dataset的长度随机选择一个下标
  27.     def getRandIndex(self):
  28.         return random.randint(0, len(self.dataset) - 1)

  29.     def clustering(self):
  30.         if self.t1 == 0:
  31.             print('Please set the threshold.')
  32.         else:
  33.             canopies = []  # 用于存放最终归类结果
  34.             while len(self.dataset) != 0:
  35.                 rand_index = self.getRandIndex()
  36.                 current_center = self.dataset[rand_index]  # 随机获取一个中心点,定为P点
  37.                 current_center_list = []  # 初始化P点的canopy类容器
  38.                 delete_list = []  # 初始化P点的删除容器
  39.                 self.dataset = np.delete(
  40.                     self.dataset, rand_index, 0)  # 删除随机选择的中心点P
  41.                 for datum_j in range(len(self.dataset)):
  42.                     datum = self.dataset[datum_j]
  43.                     distance = self.euclideanDistance(
  44.                         current_center, datum)  # 计算选取的中心点P到每个点之间的距离
  45.                     if distance < self.t1:
  46.                         # 若距离小于t1,则将点归入P点的canopy类
  47.                         current_center_list.append(datum)
  48.                     if distance < self.t2:
  49.                         delete_list.append(datum_j)  # 若小于t2则归入删除容器
  50.                 # 根据删除容器的下标,将元素从数据集中删除
  51.                 self.dataset = np.delete(self.dataset, delete_list, 0)
  52.                 canopies.append((current_center, current_center_list))
  53.         return canopies


  54. def showCanopy(canopies, dataset, t1, t2):
  55.     fig = plt.figure()
  56.     sc = fig.add_subplot(111)
  57.     colors = ['brown', 'green', 'blue', 'y', 'r', 'tan', 'dodgerblue', 'deeppink', 'orangered', 'peru', 'blue', 'y', 'r',
  58.               'gold', 'dimgray', 'darkorange', 'peru', 'blue', 'y', 'r', 'cyan', 'tan', 'orchid', 'peru', 'blue', 'y', 'r', 'sienna']
  59.     markers = ['*', 'h', 'H', '+', 'o', '1', '2', '3', ',', 'v', 'H', '+', '1', '2', '^',
  60.                '<', '>', '.', '4', 'H', '+', '1', '2', 's', 'p', 'x', 'D', 'd', '|', '_']
  61.     for i in range(len(canopies)):
  62.         canopy = canopies
  63.         center = canopy[0]
  64.         components = canopy[1]
  65.         sc.plot(center[0], center[1], marker=markers,
  66.                 color=colors, markersize=30)
  67.         t1_circle = plt.Circle(
  68.             xy=(center[0], center[1]), radius=t1, color='dodgerblue', fill=False)
  69.         t2_circle = plt.Circle(
  70.             xy=(center[0], center[1]), radius=t2, color='skyblue', alpha=0.2)
  71.         sc.add_artist(t1_circle)
  72.         sc.add_artist(t2_circle)
  73.         for component in components:
  74.             sc.plot(component[0], component[1],
  75.                     marker=markers, color=colors, markersize=1.5)
  76.     maxvalue = np.amax(dataset)
  77.     minvalue = np.amin(dataset)
  78.     plt.xlim(minvalue - t1, maxvalue + t1)
  79.     plt.ylim(minvalue - t1, maxvalue + t1)
  80.     plt.show()


  81. # 随机生成600个二维[0,1)平面点
  82. # dataset = np.random.rand(600, 2)
  83. dataset = np.array([[-3,0], [-2.5,1], [-3.5,3], [-0.5,0], [0,1.5], [0.5,2], [3,3], [2.5,4], [3.5,5]])

  84. if __name__ == '__main__':
  85.     NMax = np.max(dataset[:, 0])
  86.     NMin = np.min(dataset[:, 0])
  87.     t1 = (NMax - NMin) * 0.7
  88.     t2 = t1 * 0.75
  89.     gc = Canopy(dataset)
  90.     gc.setThreshold(t1, t2)
  91.     canopies = gc.clustering()
  92.     print('Get %s initial centers.' % len(canopies))
  93.     showCanopy(canopies, dataset, t1, t2)





红框内,指定的参数T1 ,T2。   缩小区间,质心数量增加。

另外,聚类分析好像还有 Kmeans++ ,Kmeans II 等算法估CenterPoi。






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 1明经币 +1 金钱 +15 收起 理由
qjchen + 1 + 15 赞一个!谢谢分享~

查看全部评分

发表于 2022-5-31 12:09:59 | 显示全部楼层
革天明 发表于 2022-5-29 08:23
看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可

谢谢分享~


之前觉得应该是用机器学习或者深度学习可能才能得到这个,但之前没有认真学过,不懂聚类。

于是学习了一下,颇有收获

以下是用ANACONDA的SPYDER编写PYTHON代码,主要用的sklearn

  1. # 参考 https://www.tutorialspoint.com/machine_learning_with_python/machine_learning_with_python_clustering_algorithms_k_means.htm

  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. from sklearn.cluster import KMeans

  5. XY=np.array([[-3,0], [-2.5,1], [-3.5,3], [-0.5,0], [0,1.5], [0.5,2], [3,3], [2.5,4], [3.5,5]])

  6. #显示原始数据
  7. plt.scatter(XY[:, 0], XY[:, 1], s = 30);
  8. plt.show()

  9. #人为定义为3组,y_kmeans就是预测的分组
  10. kmeans = KMeans(n_clusters = 3)
  11. kmeans.fit(XY)
  12. y_kmeans = kmeans.predict(XY)

  13. #显示聚类后的数据
  14. plt.scatter(XY[:, 0], XY[:, 1], c = y_kmeans, s = 30, cmap = 'rainbow')
  15. #显示聚类后的类中心
  16. centers = kmeans.cluster_centers_
  17. plt.scatter(centers[:, 0], centers[:, 1], c = 'blue', s = 100, alpha = 0.9);
  18. plt.show()
复制代码


结果如下:左是归类前,右是归类后


不过这个里面,人为规定了类数是3个,不知道有没有更好的自动算类的方法,但看到一般的KMEANS算法好像都有这个

后续:
假如用飞狐兄的PYCAD,估计可以编入PY插件
或者可以试试看ML.NET,看看编个C#插件可能也可以

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 1明经币 +1 金钱 +30 收起 理由
highflybird + 1 + 30 很给力!

查看全部评分

发表于 2022-5-28 11:11:20 | 显示全部楼层
几个想法聊聊。抛砖引玉。。

1.   简单法。给出选区 -> 选区x轴右侧比如[0.8,1.0]所有点
2.   均值/方差选择。给定两点(用直线、两点、窗口方式都OK)本质是给定均值和方差或方差的函数. 即可找到符合你要求的点。算量基本是O(N)
3.   色阶法。 分析全图所有点得到几种分布指标 -> 以分布指标极值附近某点为均值,方差为参数选择。 类似PS的图片色阶算法。算量约O(2~3N)。
      如果第二步不用方差鲁棒定界,指定算法或AI识别等其他,比如离散动力学估界,会指数级增加算量O(N^2) .O(N^2.5)。

算法无上限,看应用场景、成本
发表于 2022-5-28 06:43:48 | 显示全部楼层
X坐标值最大的点啊
 楼主| 发表于 2022-5-28 17:47:27 | 显示全部楼层
烟盒迷唇 发表于 2022-5-28 06:43
X坐标值最大的点啊

这只能求到最大的一个点,而不是一列点,我想求的就是最右列的所有点。
发表于 2022-5-28 17:59:29 | 显示全部楼层
烟盒迷唇 发表于 2022-5-28 06:43
X坐标值最大的点啊

这个法应该最简单
 楼主| 发表于 2022-5-28 18:09:12 | 显示全部楼层
landsat99 发表于 2022-5-28 11:11
几个想法聊聊。抛砖引玉。。

1.   简单法。给出选区 -> 选区x轴右侧比如[0.8,1.0]所有点

方差我感觉不太行,因为就如那张示意图一样,假如最左一列的所有点的X坐标相同的话,两点关于X坐标最小的方差就是最左列的点了。
发表于 2022-5-28 18:09:56 来自手机 | 显示全部楼层
随便的C# 发表于 2022-5-28 17:47
这只能求到最大的一个点,而不是一列点,我想求的就是最右列的所有点。

给X值一个公差,差值范内所有点为一列、
 楼主| 发表于 2022-5-28 18:36:00 | 显示全部楼层
自贡黄明儒 发表于 2022-5-28 18:09
给X值一个公差,差值范内所有点为一列、

这样的话就得每次都定义不同的方差范围
发表于 2022-5-29 08:23:55 | 显示全部楼层
看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可

评分

参与人数 1明经币 +1 金钱 +15 收起 理由
qjchen + 1 + 15 赞一个!

查看全部评分

 楼主| 发表于 2022-5-29 21:11:50 | 显示全部楼层
革天明 发表于 2022-5-29 08:23
看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可

感谢大佬的点拨!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 03:49 , Processed in 0.203594 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表