গ্রাফটি ব্যবহার করে শহরের ব্লকগুলি সন্ধান করা আশ্চর্যের সাথে অ-তুচ্ছ। মূলত, এটি ক্ষুদ্রতম রিংগুলির সবচেয়ে ছোট সেট (এসএসএসআর) সন্ধানের পরিমাণ, যা এনপি-সম্পূর্ণ সমস্যা। এই সমস্যার একটি পর্যালোচনা (এবং সম্পর্কিত সমস্যাগুলি) এখানে পাওয়া যাবে । তাই, একটি অ্যালগরিদম এক বিবরণ এটি বিশ্লিষ্ট করা হল এখানে । আমি যতদূর বলতে পারি, networkx
(বা সেই বিষয়টির জন্য অজগরটিতে) কোনও সম্পর্কিত বাস্তবায়ন নেই । আমি এই পদ্ধতির সংক্ষিপ্তভাবে চেষ্টা করেছি এবং তারপরে এটি ত্যাগ করেছি - আমার মস্তিষ্ক আজ সেই ধরণের কাজের জন্য স্ক্র্যাচ করতে প্রস্তুত নয়। বলা হচ্ছে, আমি যে কাউকে এই পৃষ্ঠার পরবর্তী তারিখে দেখতে এবং অ্যালগরিদমের পরীক্ষিত বাস্তবায়ন পোস্ট করতে পারে যা পাইথনে এসএসএসআর খুঁজে পায় তার জন্য আমি একটি পুরষ্কার প্রদান করব।
আমি পরিবর্তে গ্রাফটি পরিকল্পনাকারী হওয়ার নিশ্চয়তার বিষয়টি নিশ্চিত করে পৃথক পদ্ধতির অনুসরণ করেছি approach সংক্ষেপে, এটিকে গ্রাফের সমস্যা হিসাবে বিবেচনা করার পরিবর্তে আমরা এটিকে একটি চিত্র বিভাজন সমস্যা হিসাবে বিবেচনা করি। প্রথমত, আমরা চিত্রটিতে সমস্ত সংযুক্ত অঞ্চল খুঁজে পাই। তারপরে আমরা প্রতিটি অঞ্চলের চারপাশে কনট্যুর নির্ধারণ করি, চিত্রের সমন্বয়গুলিতে রূপরেখাগুলি দ্রাঘিমাংশ এবং অক্ষাংশে রূপান্তর করি।
নিম্নলিখিত আমদানি এবং ফাংশন সংজ্ঞা দেওয়া:
#!/usr/bin/env python
# coding: utf-8
"""
Find house blocks in osmnx graphs.
"""
import numpy as np
import osmnx as ox
import networkx as nx
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from skimage.measure import label, find_contours, points_in_poly
from skimage.color import label2rgb
ox.config(log_console=True, use_cache=True)
def k_core(G, k):
H = nx.Graph(G, as_view=True)
H.remove_edges_from(nx.selfloop_edges(H))
core_nodes = nx.k_core(H, k)
H = H.subgraph(core_nodes)
return G.subgraph(core_nodes)
def plot2img(fig):
# remove margins
fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
# convert to image
# https://stackoverflow.com/a/35362787/2912349
# https://stackoverflow.com/a/54334430/2912349
canvas = FigureCanvas(fig)
canvas.draw()
img_as_string, (width, height) = canvas.print_to_buffer()
as_rgba = np.fromstring(img_as_string, dtype='uint8').reshape((height, width, 4))
return as_rgba[:,:,:3]
ডেটা লোড করুন। আমদানি ক্যাশে করুন, যদি বার বার এটি পরীক্ষা করা হয় - অন্যথায় আপনার অ্যাকাউন্ট নিষিদ্ধ হতে পারে। এখানে অভিজ্ঞতা থেকে কথা বলছি।
G = ox.graph_from_address('Nørrebrogade 20, Copenhagen Municipality',
network_type='all', distance=500)
G_projected = ox.project_graph(G)
ox.save_graphml(G_projected, filename='network.graphml')
# G = ox.load_graphml('network.graphml')
নুন এবং প্রান্তগুলি ছাঁটাই যা কোনও চক্রের অংশ হতে পারে না। এই পদক্ষেপটি কঠোরভাবে প্রয়োজনীয় নয় তবে ফলস্বরূপ উত্তমরূপে আসে।
H = k_core(G, 2)
fig1, ax1 = ox.plot_graph(H, node_size=0, edge_color='k', edge_linewidth=1)
প্লটটিকে চিত্রে রূপান্তর করুন এবং সংযুক্ত অঞ্চলগুলি সন্ধান করুন:
img = plot2img(fig1)
label_image = label(img > 128)
image_label_overlay = label2rgb(label_image[:,:,0], image=img[:,:,0])
fig, ax = plt.subplots(1,1)
ax.imshow(image_label_overlay)
প্রতিটি লেবেলযুক্ত অঞ্চলের জন্য, কনট্যুর সন্ধান করুন এবং কনট্যুর পিক্সেল স্থানাঙ্কগুলিকে ডেটা স্থানাঙ্কে ফিরে রূপান্তর করুন।
# using a large region here as an example;
# however we could also loop over all unique labels, i.e.
# for ii in np.unique(labels.ravel()):
ii = np.argsort(np.bincount(label_image.ravel()))[-5]
mask = (label_image[:,:,0] == ii)
contours = find_contours(mask.astype(np.float), 0.5)
# Select the largest contiguous contour
contour = sorted(contours, key=lambda x: len(x))[-1]
# display the image and plot the contour;
# this allows us to transform the contour coordinates back to the original data cordinates
fig2, ax2 = plt.subplots()
ax2.imshow(mask, interpolation='nearest', cmap='gray')
ax2.autoscale(enable=False)
ax2.step(contour.T[1], contour.T[0], linewidth=2, c='r')
plt.close(fig2)
# first column indexes rows in images, second column indexes columns;
# therefor we need to swap contour array to get xy values
contour = np.fliplr(contour)
pixel_to_data = ax2.transData + ax2.transAxes.inverted() + ax1.transAxes + ax1.transData.inverted()
transformed_contour = pixel_to_data.transform(contour)
transformed_contour_path = Path(transformed_contour, closed=True)
patch = PathPatch(transformed_contour_path, facecolor='red')
ax1.add_patch(patch)
কনট্যুরের ভিতরে (বা চালু) পড়ার মূল গ্রাফের সমস্ত পয়েন্ট নির্ধারণ করুন।
x = G.nodes.data('x')
y = G.nodes.data('y')
xy = np.array([(x[node], y[node]) for node in G.nodes])
eps = (xy.max(axis=0) - xy.min(axis=0)).mean() / 100
is_inside = transformed_contour_path.contains_points(xy, radius=-eps)
nodes_inside_block = [node for node, flag in zip(G.nodes, is_inside) if flag]
node_size = [50 if node in nodes_inside_block else 0 for node in G.nodes]
node_color = ['r' if node in nodes_inside_block else 'k' for node in G.nodes]
fig3, ax3 = ox.plot_graph(G, node_color=node_color, node_size=node_size)
দুটি ব্লক প্রতিবেশী কিনা তা নির্ধারণ করা খুব সহজ। তারা নোড ভাগ করে নিন কিনা তা পরীক্ষা করুন:
if set(nodes_inside_block_1) & set(nodes_inside_block_2): # empty set evaluates to False
print("Blocks are neighbors.")