how to properly count the number of vehicles? - netlogo

I have a circle of radius 10 m. I want to count the number of vehicles entering the circle it (the distance from the center car <= 10m)
I'm right . I can use the toolbar "Minitor" to count the number of vehicles currently in liquidation xe.nhung "minitor" much larger than the actual number of vehicles that pass through the circle. I attached the "minitor" by "total-cars".
how to properly count the number of vehicles?
ask cars
[
if distancexy 0 0 < 10
[
set total-cars (total-cars + 1)
]
]

I am not very sure about your question, but maybe this code could help you:
set total-cars count cars with [distancexy 0 0 <= 10]
You can use the following code in the monitor control directly:
count cars with [distancexy 0 0 <= 10]

import cv2
import time
bgsMOG = cv2.createBackgroundSubtractorMOG2(detectShadows=False)
kernal=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
cap = cv2.VideoCapture(0)
counter =0
time.sleep(2)
if cap:
while True:
ret, frame = cap.read()
if ret:
#fgmask = bgsMOG.apply(frame, None, 0.01)
blur = cv2.GaussianBlur(frame, (5, 5), 0)
fgmask = bgsMOG.apply(blur)
morhpho = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernal)
#line for detection
cv2.line(frame,(20,270),(320,270),(175,175,0),5)
_,contours, hierarchy = cv2.findContours(morhpho,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
ax1=20 #coordinate of line where vehicle will be count if intersect
ay1=270
ax2=320
ay2=270
try: hierarchy = hierarchy[0]
except: hierarchy = []
#for contour, hier in zip(contours, hierarchy):
for (i, contour) in enumerate(contours):
(x,y,w,h) = cv2.boundingRect(contour)
if w > 20 and h > 25:
rec=cv2.rectangle(frame, (x,y), (x+w,y+h), (180, 0, 0), 1)
x1=w/2 #to find centroid
y1=h/2
cx=x+x1
cy=y+y1
centroid=(cx,cy)
M = cv2.moments(contour)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
# draw the contour and center of the shape on the image
cv2.circle(frame, (cX, cY), 2, (255, 255, 255), -1)
cv2.circle(frame,(int(cx),int(cy)),1,(0,255,0),-1)
dy=cY-270 #my first code to increase counter
print("centroid",cX,":",cY)
if dy==0:
if (cX<=320)and(cX>=20):
counter=counter+1
print("1st ct",counter)
print len(contour)
#FileName = "D:/data/" + str(y) + ".jpg"
#cv2.imshow("cropped",rec)
#cv2.imwrite(FileName,rec)
if cy==270:
if centroid > (27, 268) and centroid < (325, 285):
if (cX <= 320) and (cX >= 20):
counter =counter+1
print "counter=", counter
if cY > 10 and cY < 250:
cv2.putText(frame, str(counter),(10,150),cv2.FONT_HERSHEY_SIMPLEX,2, (255, 0, 0), 1, True)
#cv2.resizeWindow('Output',320,180)
cv2.imshow('Output', frame)
cv2.imshow('mor', morhpho)
cv2.imshow('blur', blur)
#cv2.imshow('FGMASK', morhpho)
key = cv2.waitKey(1)
if key == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

Related

Constrained spring layout in networkx

I have a directed graph in networkx.
The nodes have a "height" label. Here is an example with heights 0, 1, 2, 3, 4, 5 and 6:
I would like to run spring layout (in two dimensions), but constrain the nodes to be of a fixed height. That is, I want to "constrain" spring layout so that the x coordinate of the nodes moves, by the y coordinate does not.
I am relatively new to networkx. What is the best way to accomplish this? Thanks in advance.
Following #Joe's request, I'm posting answer here.
This was just a matter of patching the code suggested above together. Thus absolutely no originality is claimed.
Your graph should have a "height" variable attached to each node. Thus, once you have added the code below, the following should work:
G = nx.Graph()
G.add_edges_from([[0,1],[1,2],[2,3]])
for g in G.nodes():
G.nodes()[g]["height"] = g
draw_graph_with_height(G,figsize=(5,5))
# Copyright (C) 2004-2015 by
# Aric Hagberg <hagberg#lanl.gov>
# Dan Schult <dschult#colgate.edu>
# Pieter Swart <swart#lanl.gov>
# All rights reserved.
# BSD license.
# import numpy as np
# taken from networkx.drawing.layout and added hold_dim
def _fruchterman_reingold(A, dim=2, k=None, pos=None, fixed=None,
iterations=50, hold_dim=None):
# Position nodes in adjacency matrix A using Fruchterman-Reingold
# Entry point for NetworkX graph is fruchterman_reingold_layout()
try:
nnodes, _ = A.shape
except AttributeError:
raise RuntimeError(
"fruchterman_reingold() takes an adjacency matrix as input")
A = np.asarray(A) # make sure we have an array instead of a matrix
if pos is None:
# random initial positions
pos = np.asarray(np.random.random((nnodes, dim)), dtype=A.dtype)
else:
# make sure positions are of same type as matrix
pos = pos.astype(A.dtype)
# optimal distance between nodes
if k is None:
k = np.sqrt(1.0 / nnodes)
# the initial "temperature" is about .1 of domain area (=1x1)
# this is the largest step allowed in the dynamics.
t = 0.1
# simple cooling scheme.
# linearly step down by dt on each iteration so last iteration is size dt.
dt = t / float(iterations + 1)
delta = np.zeros((pos.shape[0], pos.shape[0], pos.shape[1]), dtype=A.dtype)
# the inscrutable (but fast) version
# this is still O(V^2)
# could use multilevel methods to speed this up significantly
for _ in range(iterations):
# matrix of difference between points
for i in range(pos.shape[1]):
delta[:, :, i] = pos[:, i, None] - pos[:, i]
# distance between points
distance = np.sqrt((delta**2).sum(axis=-1))
# enforce minimum distance of 0.01
distance = np.where(distance < 0.01, 0.01, distance)
# displacement "force"
displacement = np.transpose(np.transpose(delta)*(k * k / distance**2 - A * distance / k))\
.sum(axis=1)
# update positions
length = np.sqrt((displacement**2).sum(axis=1))
length = np.where(length < 0.01, 0.1, length)
delta_pos = np.transpose(np.transpose(displacement) * t / length)
if fixed is not None:
# don't change positions of fixed nodes
delta_pos[fixed] = 0.0
# only update y component
if hold_dim == 0:
pos[:, 1] += delta_pos[:, 1]
# only update x component
elif hold_dim == 1:
pos[:, 0] += delta_pos[:, 0]
else:
pos += delta_pos
# cool temperature
t -= dt
pos = _rescale_layout(pos)
return pos
def _rescale_layout(pos, scale=1):
# rescale to (0,pscale) in all axes
# shift origin to (0,0)
lim = 0 # max coordinate for all axes
for i in range(pos.shape[1]):
pos[:, i] -= pos[:, i].min()
lim = max(pos[:, i].max(), lim)
# rescale to (0,scale) in all directions, preserves aspect
for i in range(pos.shape[1]):
pos[:, i] *= scale / lim
return pos
def draw_graph_with_height(g,highlighted_nodes=set([]),figsize=(15,15),iterations=150,title=''):
""" Try to draw a reasonable picture of a graph with a height feature on each node."""
pos = { p : (5*np.random.random(),2*data["height"]) for (p,data) in g.nodes(data=True)} # random x, height fixed y.
pos_indices = [i for i in pos.keys()]
pos_flat = np.asarray([pos[i] for i in pos.keys()])
A = nx.adjacency_matrix(g.to_undirected())
Adense = A.todense()
Adensefloat = Adense.astype(float)
new_pos = _fruchterman_reingold(Adensefloat, dim=2, pos=pos_flat, fixed=[0,len(pos_flat)-1], iterations=iterations, hold_dim=1)
pos_dict = { pos_indices[i] : tuple(new_pos[i]) for i in range(len(pos_indices))}
# for u,v,d in g.edges(data=True):
# d['weight'] = float(d['t'][1]-d['t'][0])
# edges,weights = zip(*nx.get_edge_attributes(g,'weight').items())
# print(weights)
fig, ax = plt.subplots(figsize=figsize)
if title: fig.suptitle(title, fontsize=16)
if highlighted_nodes:
nx.draw(g, pos=pos_dict, alpha=.1, font_size=14,node_color='b')
gsub = nx.subgraph(g,highlighted_nodes)
nx.draw(gsub, pos=pos_dict, node_color='r')
else:
nx.draw(g,pos=pos_dict)
plt.show()

Generating a flat mesh that shares vertices using compute shaders

I have what seemed to be a simple problem that has now resulted in noise complaints from the neighbours over my screams of frustration.
TL;DR
Procedural meshes are normally make using strips of quads. I'm instead trying to make a mesh as one piece, reusing edge vertices, instead of lining up the quad strips as if it was one mesh.
I'm testing something so maybe this is a wierd way to do it, but it should work.
Shader 1:
RWStructuredBuffer<float3> vertexBuffer;
uniform uint yColumnHeight;
[numthreads(8,8,1)]
void calcVerts (uint3 id : SV_DispatchThreadID)
{
//convert x and y to 1 dimensional counter
int idx = (id.y + (yColumnHeight * id.x));
//create a flat array of vertices
float3 vA = float3(id.x, 1, id.y);
vertexBuffer[idx] = vA;
}
Shader 2:
RWStructuredBuffer<float3> vertexBuffer;
RWStructuredBuffer<float3> triangleBuffer;
uniform uint yColumnHeight;
[numthreads(8,8,1)]
void createMeshFromVerts (uint3 id : SV_DispatchThreadID)
{
int idx = (id.y + (yColumnHeight * id.x));
if (id.x > 0 && id.y > 0){
//convert idx to index for tri/quad vertices, skipping first row and column
int subtractFirstYColumn = idx - yColumnHeight;
int subtractFirstXRow = id.y - 1;
int trID = (subtractFirstYColumn - subtractFirstXRow) * 6;
//find the vertices of the quad using verts from first row and column
int tri_a = idx - yColumnHeight - 1;
int tri_b = idx - 1;
int tri_c = idx;
int tri_d = idx - yColumnHeight;
triangleBuffer[trID] = vertexBuffer[tri_a];
triangleBuffer[trID + 1] = vertexBuffer[tri_b];
triangleBuffer[trID + 2] = vertexBuffer[tri_c];
triangleBuffer[trID + 3] = vertexBuffer[tri_d];
triangleBuffer[trID + 4] = vertexBuffer[tri_a];
triangleBuffer[trID + 5] = vertexBuffer[tri_c];
}
}
The second shader may initially seem obtuse, but it's quite simple. I'm getting an array of verts:
. . . .
. . . .
. . . .
. . . .
In the above, that's a 3x3 grid of quads, made of 4x4 verts.
I start by getting the vert 1 across and 1 down, and making a quad with the top left corner verts.
Each quad starts with vert _ and uses preceeding verts . like this:
. .
. _
And tied together in the main C#:
//buffers for vertices and map of vertices to make triangles
vertexBuffer = new ComputeBuffer(triVertCount, stride, ComputeBufferType.Default);
triangleBuffer = new ComputeBuffer(tris, stride, ComputeBufferType.Default);
//create initial vertices grid
calcVerts.SetBuffer(verts, "vertexBuffer", vertexBuffer);
calcVerts.Dispatch(verts, Mathf.Max(1, (widthInVertices) / (int)threadsx), Mathf.Max(1, (heightInVertices) / (int)threadsy), (int)z);
//use vertices grid to make mesh
createMeshFromVerts.SetBuffer(meshFromVerts, "vertexBuffer", vertexBuffer);
createMeshFromVerts.SetBuffer(meshFromVerts, "triangleBuffer", triangleBuffer);
createMeshFromVerts.Dispatch(meshFromVerts, Mathf.Max(1, (widthInVertices) / (int)threadsx), Mathf.Max(1, (heightInVertices) / (int)threadsy), (int)z);
I skipped the code for normals, and where I pass to material to render. When this runs I get scrambled triangles. Can you see where I messed up?
The calculation of trId results in overlapping of some indices, and skipping of other values.
With a 4x2 grid of vertices (idx shown) and yColumnHeight of 4:
0 4
x <- (desired trID 0)
1 5
x <- (desired trID 6)
2 6
x <- (desired trID 12)
3 7
The currently calculated trId for id = 1,1 (idx 5) comes out to 6, but it should probably come to 0 so that the first 6 items in the triangleBuffer are set to something useful. In fact, no trId ever equals 0 using the current calculation. Furthermore, the currently calculated trId for id = 1,2 (idx 6) comes out to 6 as well! And so does id=1,3 (idx 7).
Sadly, this overlap occurs in every column, and most of the triangleBuffer goes unset as a result of this.
The answer is to change how trId is calculated.
A simple way is to re-use your method of mapping from 2d to 1d array, only reducing the x and y coordinates by 1 and also reducing the height by one:
Vertex mapping (current):
int idx = (id.y + (yColumnHeight * id.x));
Triangle mapping (proposed):
int trId = ((id.y-1) + ((yColumnHeight-1) * (id.x-1));
trId *= 6;
or more simply:
int trId = 6 * (id.y - 1 + (yColumnHeight-1) * (id.x-1));
or, expanding and substituting idx. I find this less clear what's happening but it's more succinct:
// = 6 * (id.y - 1 + yColumnHeight * id.x - yColumnHeight - id.x + 1)
// = 6 * (id.y + yColumnHeight * id.x - yColumnHeight - id.x)
int trId = 6 * (idx - yColumnHeight - id.x);

in Ipython a function named display gives me an error

# Kepler's Laws.py
# plots the orbit of a planet in an eccentric orbit to illustrate
# the sweeping out of equal areas in equal times, with sun at focus
# The eccentricity of the orbit is random and determined by the initial velocity
# program uses normalised units (G =1)
# program by Peter Borcherds, University of Birmingham, England
from vpython import *
from random import random
from IPython import display
import pandas as pd
def MonthStep(time, offset=20, whole=1): # mark the end of each "month"
global ccolor # have to make it global, since label uses it before it is updated
if whole:
Ltext = str(int(time * 2 + dt)) # end of 'month', printing twice time gives about 12 'months' in 'year'
else:
Ltext = duration + str(time * 2) + ' "months"\n Initial speed: ' + str(round(speed, 3))
ccolor = color.white
label(pos=planet.pos, text=Ltext, color=ccolor,
xoffset=offset * planet.pos.x, yoffset=offset * planet.pos.y)
ccolor = (0.5 * (1 + random()), random(), random()) # randomise colour of radial vector
return ccolor
scene = display(title="Kepler's law of equal areas", width=1000, height=1000, range=3.2)
duration = 'Period: '
sun = sphere(color=color.yellow, radius=0.1) # motion of sun is ignored (or centre of mass coordinates)
scale = 1.0
poss = vector(0, scale, 0)
planet = sphere(pos=poss, color=color.cyan, radius=0.02)
while 1:
velocity = -vector(0.7 + 0.5 * random(), 0, 0) # gives a satisfactory range of eccentricities
##velocity = -vector(0.984,0,0) # gives period of 12.0 "months"
speed = mag(velocity)
steps = 20
dt = 0.5 / float(steps)
step = 0
time = 0
ccolor = color.white
oldpos = vector(planet.pos)
ccolor = MonthStep(time)
curve(pos=[sun.pos, planet.pos], color=ccolor)
while not (oldpos.x > 0 and planet.pos.x < 0):
rate(steps * 2) # keep rate down so that development of orbit can be followed
time += dt
oldpos = vector(planet.pos) # construction vector(planet.pos) makes oldpos a varible in its own right
# oldpos = planet.pos makes "oldposs" point to "planet.pos"
# oldposs = planet.pos[:] does not work, because vector does not permit slicing
denom = mag(planet.pos) ** 3
velocity -= planet.pos * dt / denom # inverse square law; force points toward sun
planet.pos += velocity * dt
# plot orbit
curve(pos=[oldpos, planet.pos], color=color.red)
step += 1
if step == steps:
step = 0
ccolor = MonthStep(time)
curve(pos=[sun.pos, planet.pos], color=color.white)
else:
# plot radius vector
curve(pos=[sun.pos, planet.pos], color=ccolor)
if scene.kb.keys:
print
"key pressed"
duration = 'Duration: '
break
MonthStep(time, 50, 0)
label(pos=(2.5, -2.5, 0), text='Click for another orbit')
scene.mouse.getclick()
for obj in scene.objects:
if obj is sun or obj is planet: continue
obj.visible = 0 # clear the screen to do it again
I copied Kepler's Laws code in google and compiled it on pycharm.
But there is an error that
scene = display(title="Kepler's law of equal areas", width=1000, height=1000, range=3.2)
TypeError: 'module' object is not callable
I found some information on google that "pandas" library can improve this error so I tried it but I can't improve this error.
What should I do?
Replace "display" with "canvas", which is the correct name of this entity.

How to detect curve shaped clusters in 2D array? Python

What is the smartest way to detect curves in a 2d dataset? There must be a way to cluster data points by defining maximum distance to neighbor. My goal is to apply polyfit function over each curve and use this template for alike datasets.
Example of data:
array([[ 0., 0., 0., ..., 2020., 2020., 2020.],
[ 51., 76., 194., ..., 1862., 1915., 2021.]])
Figured out this can be done with Agglomerative Clustering, here's the code and result:
from sklearn.cluster import AgglomerativeClustering
#Reshape data
a = array[:, 0].flatten()
b = array[:, 1].flatten()
array_new = np.matrix([a,b])
array_new = np.squeeze(np.asarray(array_new))
array_new1 = array_new.T
#Clustering algorithm
n_clusters = None
model = AgglomerativeClustering(n_clusters=n_clusters,
affinity='euclidean',
linkage='single',
compute_full_tree=True,
distance_threshold=15)
model.fit(array_new1)
labels = model.labels_
n_clusters = len(list(set(labels)))
print(n_clusters)
cmap = plt.get_cmap('rainbow')
colors = [cmap(i) for i in np.linspace(0, 1, n_clusters)]
plt.figure(figsize=(15,15))
for i, color in enumerate(colors, start=1):
plt.scatter(array_new1[labels==i,0], array_new1[labels==i,1], color=color)
plt.gca().invert_yaxis()
plt.show()
![](https://i.stack.imgur.com/utwqP.png)
#plotting result
data = pd.DataFrame({'x' : array_new1[:,0],
'y' : array_new1[:,1],
'label' : labels})
data.sort_values(by='label')
counter = 0
plt.figure(figsize=(15,15))
plt.scatter(5*array[:, 0], array[:, 1])
for i in range(n_clusters):
if len(data.loc[data['label'] == i].iloc[:,0]) > 50 \
and len(data.loc[data['label'] == i].iloc[:,0]) < 1000:
counter += 1
z = np.polyfit(data.loc[data['label'] == i].iloc[:,0],
data.loc[data['label'] == i].iloc[:,1],
2)
p = np.poly1d(z)
xp = np.linspace(0, tasku_sk, 50)
#plt.scatter(data.loc[data['label'] == i].iloc[:,0],
# data.loc[data['label'] == i].iloc[:,1])
plt.plot(5*xp, p(xp), c='r', lw=4)
plt.gca().invert_yaxis()
plt.show()
print(counter)
![](https://i.stack.imgur.com/AQHOf.png)
22
Yes.
The supposedly oldest of all clustering algorithms: single-link.

Image outline using python/PIL

I have a color photo of apple, how can I show only its outline (inside white, background black) with python/PIL?
Something like this should work.
from PIL import Image, ImageFilter
image = Image.open('your_image.png')
image = image.filter(ImageFilter.FIND_EDGES)
image.save('new_name.png')
If that doesn't give you the result you are looking for then you try implementing either Prewitt edge detection, Sobel edge detection or Canny edge detection using PIL and Python and other libraries see related question and the following example .
If you are trying to do particle detection / analysis rather than just edge detection, you can try using py4ij to call the ImageJ method you link to give you expect the same result, or try another Particle Analysis Python library EMAN alternately you can write a Particle detection algorithm using PIL, SciPy and NumPy.
If your object and background have fairly well contrast
from PIL import Image
image = Image.open(your_image_file)
mask=image.convert("L")
th=150 # the value has to be adjusted for an image of interest
mask = mask.point(lambda i: i < th and 255)
mask.save(file_where_to_save_result)
if higher contrast is in one (of 3 colors), you may split the image into bands instead of converting it into grey scale.
if an image or background is fairly complicated, more sophisticated processing will be required
Apple vs Lines
You can do it just using PIL and Python in less than 200 lines of code. Would be easier to use canny-edge-detection from a library.
Here is the steps. Convert to grayscale for lumens. Using kernel image processing detect edges using Sobel. Thin the edge using the magnitude and slope obtain from Sobel.
from PIL import Image
import math
def one_to_two_dimension_array(list_,columns):
#use list slice
return [ list_[i:i+columns] for i in range(0, len(list_),columns) ]
def flatten_matrix(matrix):
return [val for sublist in matrix for val in sublist]
def matrix_convole(matrix, kernel_matrix, multiplier):
return_list=[]
return_matrix=[]
border=(len(kernel_matrix) - 1) / 2;border=int(border)
center_kernel_pos=border
for matrix_row in range( len( matrix )):
for matrix_col in range(len( matrix[matrix_row] ) ):
accumulator = 0
if (matrix_row - border)<0 or \
(matrix_col-border)< 0 or \
(matrix_row+border) > (len( matrix )-border) or \
(matrix_col+border) > (len( matrix[matrix_row] )-border):
return_list.append(matrix[matrix_row][matrix_col])
continue
for kernel_row in range(len (kernel_matrix) ):
for kernel_col in range(len (kernel_matrix[kernel_row]) ):
relative_row= kernel_row - center_kernel_pos
relative_col= kernel_col - center_kernel_pos
kernel = kernel_matrix[kernel_row][kernel_col]
pixel = matrix [matrix_row + relative_row] [matrix_col + relative_col]
accumulator += pixel * kernel
return_list.append(accumulator* multiplier )
return_matrix = one_to_two_dimension_array( return_list, len( matrix[0] ) )
return return_matrix
def canny_round_degree(deg):
#0, 22.5, 45, 67.5, 90, 112.5, 135, 157.5, 180
if deg >= 0 and deg <= 22.5:
return 0
elif deg >= 22.5 and deg <= 67.5:
return 45
elif deg > 67.5 and deg <=112.5:
return 90
elif deg > 112.5 and deg <=157.5:
return 135
elif deg >= 157.5 and deg <= 180:
return 0
if deg <= 0 and deg >= -22.5:
return 0
elif deg <= -22.5 and deg >= -67.5:
return 135
elif deg < -67.5 and deg >= -112.5:
return 90
elif deg < -112.5 and deg >= -157.5:
return 45
elif deg <= -157.5 and deg >= -180:
return 0
image_path='apple.jpg'
gaussian_5x5_kernel=[[2,4,5,4,2],[4,9,12,9,4],[5,12,15,12,5],[4,9,12,9,4],[2,4,5,4,2]] #multiplier 1/159
sobel_kernel_gx=[[-1,0,1],[-2,0,2],[-1,0,1]]
sobel_kernel_gy=[[-1,-2,-1],[0,0,0],[1,2,1]]
im_list=list(Image.open(image_path).convert('L').getdata(0)) #grayscale, get first channel
im_width=Image.open(image_path).width
im_height=Image.open(image_path).height
im_matrix = one_to_two_dimension_array(im_list, im_width)
im_matrix_blur=matrix_convole(im_matrix,gaussian_5x5_kernel, 1/159)
sobel_gx_matrix=matrix_convole(im_matrix_blur,sobel_kernel_gx, 1)
sobel_gy_matrix=matrix_convole(im_matrix_blur,sobel_kernel_gy, 1)
sobel_gy_list=flatten_matrix(sobel_gy_matrix)
sobel_gx_list=flatten_matrix(sobel_gx_matrix)
sobel_g_magnitude_list = [math.hypot(gy,gx) for gx,gy in zip(sobel_gx_list,sobel_gy_list)]
sobel_g_angle_list = [ canny_round_degree(math.degrees(math.atan2(gy,gx))) for gx,gy in zip(sobel_gx_list,sobel_gy_list)]
sobel_g_angle_matrix = one_to_two_dimension_array(sobel_g_angle_list, im_width)
sobel_g_magnitude_matrix = one_to_two_dimension_array(sobel_g_magnitude_list, im_width)
suppression_list = []
for s_row in range( len( sobel_g_angle_matrix)):
for s_col in range(len( sobel_g_angle_matrix[s_row] ) ):
if (s_row - 1)<0 or \
(s_col-1)< 0 or \
(s_row+1) > (len( sobel_g_angle_matrix )-1) or \
(s_col+1) > (len( sobel_g_angle_matrix[s_row] )-1):
suppression_list.append(0)
continue
magnitude_in_question = sobel_g_magnitude_matrix[s_row][s_col]
#thresholding magnitude continue, arbitrary 129
if magnitude_in_question < 36:
suppression_list.append(0)
continue
angle_in_question = sobel_g_angle_matrix[s_row][s_col]
east_magnitude = sobel_g_magnitude_matrix[s_row][s_col-1]
west_magnitude = sobel_g_magnitude_matrix[s_row][s_col+1]
north_magnitude = sobel_g_magnitude_matrix[s_row-1][s_col]
south_magnitude = sobel_g_magnitude_matrix[s_row+1][s_col]
north_east_magnitude = sobel_g_magnitude_matrix[s_row-1][s_col-1]
north_west_magnitude = sobel_g_magnitude_matrix[s_row-1][s_col+1]
south_east_magnitude = sobel_g_magnitude_matrix[s_row+1][s_col-1]
south_west_magnitude = sobel_g_magnitude_matrix[s_row+1][s_col+1]
if angle_in_question == 0 and magnitude_in_question > east_magnitude \
and magnitude_in_question > west_magnitude:
suppression_list.append(1)
elif angle_in_question == 90 and magnitude_in_question > north_magnitude \
and magnitude_in_question > south_magnitude:
suppression_list.append(1)
elif angle_in_question == 135 and magnitude_in_question > north_west_magnitude \
and magnitude_in_question > south_east_magnitude:
suppression_list.append(1)
elif angle_in_question == 45 and magnitude_in_question > north_east_magnitude \
and magnitude_in_question > south_west_magnitude:
suppression_list.append(1)
else:
suppression_list.append(0)
new_img = Image.new('1', (im_width,im_height)) #bw=1;grayscale =L
new_img.putdata( suppression_list )
new_img.save('apple-lines.png', 'PNG')