Python: Draw line between two coordinates in a matrix
This is one simple implementation with NumPy, just computing the line equation:
import numpy as np
def draw_line(mat, x0, y0, x1, y1, inplace=False):
if not (0 <= x0 < mat.shape[0] and 0 <= x1 < mat.shape[0] and
0 <= y0 < mat.shape[1] and 0 <= y1 < mat.shape[1]):
raise ValueError('Invalid coordinates.')
if not inplace:
mat = mat.copy()
if (x0, y0) == (x1, y1):
mat[x0, y0] = 2
return mat if not inplace else None
# Swap axes if Y slope is smaller than X slope
transpose = abs(x1 - x0) < abs(y1 - y0)
if transpose:
mat = mat.T
x0, y0, x1, y1 = y0, x0, y1, x1
# Swap line direction to go left-to-right if necessary
if x0 > x1:
x0, y0, x1, y1 = x1, y1, x0, y0
# Write line ends
mat[x0, y0] = 2
mat[x1, y1] = 2
# Compute intermediate coordinates using line equation
x = np.arange(x0 + 1, x1)
y = np.round(((y1 - y0) / (x1 - x0)) * (x - x0) + y0).astype(x.dtype)
# Write intermediate coordinates
mat[x, y] = 1
if not inplace:
return mat if not transpose else mat.T
Some tests:
print(draw_line(np.zeros((5, 5)), 0, 3, 4, 2))
#[[0. 0. 0. 2. 0.]
# [0. 0. 0. 1. 0.]
# [0. 0. 1. 0. 0.]
# [0. 0. 1. 0. 0.]
# [0. 0. 2. 0. 0.]]
print(draw_line(np.zeros((5, 5)), 4, 2, 0, 3))
#[[0. 0. 0. 2. 0.]
# [0. 0. 0. 1. 0.]
# [0. 0. 1. 0. 0.]
# [0. 0. 1. 0. 0.]
# [0. 0. 2. 0. 0.]]
print(draw_line(np.zeros((5, 5)), 1, 0, 3, 4))
#[[0. 0. 0. 0. 0.]
# [2. 0. 0. 0. 0.]
# [0. 1. 1. 1. 0.]
# [0. 0. 0. 0. 2.]
# [0. 0. 0. 0. 0.]]
draw grid lines between same values in a matrix in python
Using only matplotlib :
import matplotlib.pyplot as plt
mat = [[0.2, 0.2, 0.1, 0.1, 0.1],
[0.2, 0.2, 0.1, 0.1, 0.0],
[0.2, 0.2, 0.1, 0.1, 0.0],
[0.2, 0.1, 0.1, 0.0, 0.0]]
def line(x,y):
plt.plot(x,y,marker = 'o',color = 'red',
markerfacecolor='black',markeredgecolor='black')
def draw(mat):
for i in range(len(mat)):
for k in range(len(mat[i])-1):
if mat[i][k] == mat[i][k+1] :
line([k,k+1],[len(mat)-i,len(mat)-i])
for i in range(len(mat)-1):
for k in range(len(mat[i])):
if mat[i][k] == mat[i+1][k]:
line([k,k],[len(mat)-i,len(mat)-i-1])
draw(mat)
plt.show()
In python interpolate a line of values between two points on a 2d grid of zeroes
So thanks to Ardweaden for suggesting I find a simple way to state my objective, and Mad Physicist for pointing me in the direction at the Bresenham line algorithm. After that I was able to find a couple python implementation that bridged the gap. The working code for two versions is below (if anyone has a faster way to do it I will mark that as the accepted answer):
#Starting from the line limits obtained in the original questions code
x0 = np.ceil(line_array[0][start[0]]) #first filled element on x
y0 = np.ceil(line_array[1][start[0]]) #first filled element on y
x1 = np.floor(line_array[0][end[(len(end) - 1)]]) #last filled element on x
y1 = np.floor(line_array[1][end[(len(end) - 1)]]) #last filled element on y
#The skimage implementation of Bresenham's line algorithm
# https://scikit-image.org/docs/dev/api/skimage.draw.html#skimage.draw.line
from skimage.draw import line
#Make a 2d array of 0s that is the same size as the original 2d array z
V = np.zeros((z.shape[0], z.shape[1]), dtype=np.uint8)
#This flips the y and x from how I think of it...
rr, cc = line(int(y0), int(x0), int(y1), int(x1))
#Cast the line coordinates as 1s
V[rr, cc] = 1
#Then add the new array to the old array (although could just write the line on z).
new_z = V + z
#Use numpy where to change the 2 values back to 1 values.
new_z[np.where(new_z==2)] = 1
#Show the final image
plt.imshow(new_z)
# This implementation is a short script from https://github.com/encukou/bresenham and can just be
# brought into the existing code base without importing an external library.
# The code can be modified, but as is doesn't have a return so place it into a list
new_line = list(bresenham(int(y0), int(x0), int(y1), int(x1)))
#Use list comprehension to get the arrays
x_array = np.array([item[0] for item in new_line])
y_array = np.array([item[1] for item in new_line])
#Then cast them as 1's
V[x_array, y_array] = 1
#Combine the original and the new array
new_z = V + z
#Recast the 2's to 1's
new_z[np.where(new_z==2)] = 1
#And view
plt.imshow(new_z)
How to draw lines between points in OpenCV?
Using draw contours, you can draw the shape all at once.
img = np.zeros([512, 512, 3],np.uint8)
a = np.array([(375, 193), (364, 113), (277, 20), (271, 16), (52, 106), (133, 266), (289, 296), (372, 282)])
cv2.drawContours(img, [a], 0, (255,255,255), 2)
If you don't want the image closed and want to continue how you started:
image = np.zeros([512, 512, 3],np.uint8)
pointsInside = [(375, 193), (364, 113), (277, 20), (271, 16), (52, 106), (133, 266), (289, 296), (372, 282)]
for index, item in enumerate(pointsInside):
if index == len(pointsInside) -1:
break
cv2.line(image, item, pointsInside[index + 1], [0, 255, 0], 2)
Regarding your current code, it looks like you are trying to access the next point by indexing the current point. You need to check for the next point in the original array.
A more Pythonic way of doing the second version would be:
for point1, point2 in zip(a, a[1:]):
cv2.line(image, point1, point2, [0, 255, 0], 2)
Plotting lines connecting points
I think you're going to need separate lines for each segment:
import numpy as np
import matplotlib.pyplot as plt
x, y = np.random.random(size=(2,10))
for i in range(0, len(x), 2):
plt.plot(x[i:i+2], y[i:i+2], 'ro-')
plt.show()
(The numpy
import is just to set up some random 2x10 sample data)
Related Topics
Python Xlsxwriter Set Border Around Multiple Cells
How to Name Dataframes Dynamically in Python
Add Padding to Images to Get Them into the Same Shape
How to Add Multiple Embed Images in an Email Using Python
Python: Opencv - Selecting Region of an Image
How to Close Child Window in Tkinter
The Right Way to Limit Maximum Number of Threads Running At Once
How to Test If an Enum Member With a Certain Name Exists
How to Find the Average Colour of an Image in Python With Opencv
How to Align Labels and Entry Boxes in a Gui Program
Changing Only One Row to Column in Python
What Does Sqlite3.Operationalerror: Near "-": Syntax Error Mean
How to Delete All Columns in Dataframe Except Certain Ones
How to Read Multiple Lines of Raw Input