How to Draw a Line on a Image

how to draw a line on a image?

"Draw a line on a bmp image which is pass into a method using drawline method in C#"

PaintEventArgs e would suggest that you are doing this during the "paint" event for an object. Since you are calling this in a method, then no you do not need to add PaintEventArgs e anywhere.

To do this in a method, use @BFree's answer.

public void DrawLineInt(Bitmap bmp)
{
Pen blackPen = new Pen(Color.Black, 3);

int x1 = 100;
int y1 = 100;
int x2 = 500;
int y2 = 100;
// Draw line to screen.
using(var graphics = Graphics.FromImage(bmp))
{
graphics.DrawLine(blackPen, x1, y1, x2, y2);
}
}

The "Paint" event is raised when the object is redrawn. For more information see:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.paint.aspx

How to draw a line on an image in OpenCV?

Just calculate for 2 points outside. opencv's Line is fine with e.g. (-10,-10) for a point.

import cv2  # python-opencv
import numpy as np

width, height = 800, 600
x1, y1 = 0, 0
x2, y2 = 200, 400
image = np.ones((height, width)) * 255

line_thickness = 2
cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), thickness=line_thickness)

http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html#cv2.line

How can I draw line for an image in python

You may fit an ellipse as described in the following post.

Code sample:

import cv2
import numpy as np
import math

img = cv2.pyrDown(cv2.imread("brain_ct.png", cv2.IMREAD_COLOR))

# threshold image
ret, threshed_img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY),
127, 255, cv2.THRESH_BINARY)
# find contours and get the external one
contours, hier = cv2.findContours(threshed_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # Use cv2.RETR_EXTERNAL for getting the external contour

# find the biggest contour (c) by the area
c = max(contours, key = cv2.contourArea)

(x,y),(MA,ma),angle = cv2.fitEllipse(c)

cv2.ellipse(img, ((x,y), (MA,ma), angle), color=(0, 255, 0), thickness=2)

# https://stackoverflow.com/questions/62698756/opencv-calculating-orientation-angle-of-major-and-minor-axis-of-ellipse
rmajor = max(MA,ma)/2
if angle > 90:
angle -= 90
else:
angle += 90
xtop = x + math.cos(math.radians(angle))*rmajor
ytop = y + math.sin(math.radians(angle))*rmajor
xbot = x + math.cos(math.radians(angle+180))*rmajor
ybot = y + math.sin(math.radians(angle+180))*rmajor
cv2.line(img, (int(xtop),int(ytop)), (int(xbot),int(ybot)), (0, 255, 0), 3)

cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result:

Sample Image

Getting the exact line is a lot harder...


Rotating the image:

  • Set the center to the center of mass:

     # https://stackoverflow.com/questions/49582008/center-of-mass-in-contour-python-opencv
    m = cv2.moments(c)
    cx = int(m["m10"] / m["m00"])
    cy = int(m["m01"] / m["m00"])
    M = cv2.getRotationMatrix2D((cx, cy), angle-90, 1) # Get transformation matrix - for rotating by angle, set the center to the center of the ellipse.
  • Set the center to the center of the ellipse:

     M = cv2.getRotationMatrix2D((x, y), angle-90, 1)  # Get transformation matrix - for rotating by angle, set the center to the center of the ellipse.

    img = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]), cv2.INTER_CUBIC)

Result:

Sample Image

drawing a line on an image with PIL

This should work:

from PIL import Image, ImageDraw
im = Image.new('RGBA', (400, 400), (0, 255, 0, 255))
draw = ImageDraw.Draw(im)
draw.line((100,200, 150,300), fill=128)
im.show()

Basically using ImageDraw draw over the image, then display that image after changes, to draw a thick line pass width

draw.line((100,200, 150, 300), fill=128, width=3)

Draw a line on an image using angle and center point using Python

Thanks for posting your solution. I've found a good one.

import math

def get_coords(x, y, angle, imwidth, imheight):

x1_length = (x-imwidth) / math.cos(angle)
y1_length = (y-imheight) / math.sin(angle)
length = max(abs(x1_length), abs(y1_length))
endx1 = x + length * math.cos(math.radians(angle))
endy1 = y + length * math.sin(math.radians(angle))

x2_length = (x-imwidth) / math.cos(angle+180)
y2_length = (y-imheight) / math.sin(angle+180)
length = max(abs(x2_length), abs(y2_length))
endx2 = x + length * math.cos(math.radians(angle+180))
endy2 = y + length * math.sin(math.radians(angle+180))

return endx1, endy1, endx2, endy2

Then I just draw a line between (endx1, endy1) and (endx2, endy2).

If you have a better solution, I would be very interested to see it.

How to draw a line on image and retrieve pixels beneath the line?

I was a little confused by your question; But I guess if I misunderstood the problem; it may help someone else later. I tried to test it with @Dan Mašek method.

from tkinter import *
import numpy as np
import cv2
import sys
import PIL.Image as imge
import PIL.ImageTk as imtk

curPth = sys.path[0]
imgPth = curPth+'/back.png'
tmpPth = curPth+'/temp.png'

ev = None
thikness = 40

def click(event):
global ev, back, lbl
if ev == None:
ev = event
return None

im = cv2.imread(imgPth)
mask = cv2.cvtColor(im.copy()*0, cv2.COLOR_BGR2GRAY)
cv2.line(mask, pt1=(ev.x, ev.y), pt2=(event.x, event.y),
color=(255, 0, 0), thickness=thikness)
mask = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)[1]
out = im.copy()
out[np.where(mask == 0)] = 255

out = cv2.cvtColor(out, cv2.COLOR_BGR2RGB)
back = imtk.PhotoImage(image=imge.fromarray(out))
lbl.config(image=back)

# print(mask[np.where(mask == 255)])
x, X = min(ev.x, event.x)-thikness//2, max(ev.x, event.x)+thikness//2
y, Y = min(ev.y, event.y)-thikness//2, max(ev.y, event.y)+thikness//2
cropped = mask[y:Y, x:X]
print(cropped, cropped.shape)
cv2.imwrite(curPth+'/2d_line_area.png', cropped)
ev = event

root = Tk()
back = PhotoImage(file=imgPth)
lbl = Label(root, image=back)
lbl.place(x=0, y=0)
root.bind('<Button-1>', lambda event: click(event))
root.mainloop()

My test image that I draw with paint.net:

Sample Image

Tkinter main loop:

Sample Image

After click on 2 points on screen:

Sample Image

And more tests:

Sample Image


Two-dimensional array only from the area where the line is drawn.

Sample Image

Sample Image

Sample Image


More examples:

x, X = min(ev.x, event.x)-thikness//2, max(ev.x, event.x)+thikness//2
y, Y = min(ev.y, event.y)-thikness//2, max(ev.y, event.y)+thikness//2
cropped1 = mask[y:Y, x:X]
cropped2 = out[y:Y, x:X]
print(cropped1, cropped1.shape)
cropped1=cv2.cvtColor(cropped1,cv2.COLOR_GRAY2RGB)
cropped2=cv2.cvtColor(cropped2,cv2.COLOR_BGR2RGB)
cv2.imwrite(curPth+'/2d_line_area.png', np.hstack((cropped1,cropped2)))
ev = event

Sample Image

Sample Image

Draw a Line in OpenCV and Python beyond given points

Drawing a line between two points is like drawing a triangle.
I got a proportion by using the greater of the distances on the x and y axis, and by enlarging my triangle to the screen dimensions, I reached the line you want.

import cv2
import numpy as np

sizeofscr = 500

blank_image = np.zeros((sizeofscr,sizeofscr,3), np.uint8)

p1 = (290,230)
p2 = (100,100)

blank_image = cv2.circle(blank_image, p1, 10, (255, 0, 0), 2)
blank_image = cv2.circle(blank_image, p2, 10, (255, 0, 0), 2)

fx = abs(p1[0] - p2[0])
fy = abs(p1[1] - p2[1])

if (p1[0]+p1[1]) > (p2[0]+p2[1]):
if fx < fy:
temp = abs(sizeofscr - p1[1]) / fy

fx = (temp * fx) + p1[0]
fy = (temp * fy) + p1[1]

blank_image = cv2.line(blank_image,(int(fx),int(fy)),p2,(0,0,255),3)

else:
temp = abs(sizeofscr - p1[0]) / fx

fx = (temp * fx) + p1[0]
fy = (temp * fy) + p1[1]

blank_image = cv2.line(blank_image,(int(fx),int(fy)),p2,(0,0,255),3)
else:
if fx < fy:
temp = abs(sizeofscr - p1[1]) / fy

fx = (temp * fx) + p1[0]
fy = (temp * fy) + p1[1]

blank_image = cv2.line(blank_image,(int(fx),int(fy)),p1,(0,0,255),3)
else:
temp = abs(sizeofscr - p1[0]) / fx

fx = (temp * fx) + p1[0]
fy = (temp * fy) + p1[1]


blank_image = cv2.line(blank_image,(int(fx),int(fy)),p1,(0,0,255),3)

cv2.imshow("test",blank_image)
cv2.waitKey(0)

result:

Sample Image



Related Topics



Leave a reply



Submit