Ask Your Question
0

How do I draw a scale inside the bounding box?

asked 2017-12-12 03:28:29 -0600

Santhosh1 gravatar image

I want to measure the dimension of the objects in a image.

This is my original image

image description

These are bounding box that I have drawn around the detected objects

image description

As can be seen even the shadow is being detected as area under the interested object.

Unfortunately, I doubt manipulating the image in any way can help me minimise the error in me detecting a wrong dimension.

I would like to draw draw small lines inside on two sides of the bounding box as can seen on the ruler image below

image description

Which definitely will help me get a accurate measurement without manipulating the original image in any way

Can any suggestion how this can be done?

edit retag flag offensive close merge delete

Comments

1

for accurate measurement first you need a camera calibration and second either an object with known size or a fixed working distance. Doing this you are able to compare the real world with the virtual one. Otherwise its not possible.

VxW gravatar imageVxW ( 2017-12-12 04:03:45 -0600 )edit

@VxW Considering that the about conditions are met. I just want to draw small lines(as seen on ruler in mm) on two sides of the inside the bounding box.

Santhosh1 gravatar imageSanthosh1 ( 2017-12-12 04:09:42 -0600 )edit
1

you can iterate along the lines using LineIterator (see here), calculate the normal vector and draw the lines using cv::lines. Additionally you will need a scale parameter of your iteration steps (distance between the small ruler lines)

VxW gravatar imageVxW ( 2017-12-12 04:29:10 -0600 )edit

3 answers

Sort by ยป oldest newest most voted
2

answered 2017-12-13 05:02:01 -0600

Santhosh1 gravatar image

updated 2017-12-13 05:04:55 -0600

I solved it ๐Ÿ˜Š

This is the solution I was looking for though I couldn't extend the lines from the points. This solves my problem.

image description

image description

Just found the length of the line segment.

Then used the m:n ratio of dividing the line segment at pre set interval

Find the point's coordinates, then draw a set circle at the point

10 line code I guess anyone can do it after they get the idea

edit flag offensive delete link more

Comments

Easier way to do it by using mouse event function.

supra56 gravatar imagesupra56 ( 2017-12-13 06:55:34 -0600 )edit

@supra56 No manual intervention. It has to detect the object by itself and draw out such a scale. I just cropped the image as I couldn't upload the entire pic

Santhosh1 gravatar imageSanthosh1 ( 2017-12-14 00:29:04 -0600 )edit
0

answered 2017-12-12 08:28:23 -0600

moHe gravatar image

updated 2017-12-12 08:30:00 -0600

Hi, I've drawn one line in my poor code T_T, but I don't have time now to transform it into the iterative one: draw parallel lines along the shorter side to divide the rect into 2, 4, 8, ... parts, hope this can help you a bit:)

I'll try to spare time to turn it into a iterative one.

import cv2
import numpy as np
import matplotlib.pyplot as plt


img = cv2.imread("./a.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, thr = cv2.threshold(gray, 127, 255, cv2.THRESH_OTSU)
_, contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
small_cnts = [i for i in contours if cv2.contourArea(i) < 100]
cv2.fillPoly(thr, small_cnts, 0)
_, cnts, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key=lambda x: cv2.contourArea(x))
cnts.pop()

img_cp = img.copy()
[cv2.drawContours(img_cp, contours, i, (255, 0, 0), thickness=3) for i in range(len(contours))]
plt.imshow(cv2.cvtColor(img_cp, cv2.COLOR_BGR2RGB))
plt.show()

cnt_0 = cnts[0]
cnt_1 = cnts[1]
rect_0 = cv2.minAreaRect(cnt_0)
rect_1 = cv2.minAreaRect(cnt_1)
box_0 = cv2.boxPoints(rect_0).astype(np.int0)
box_1 = cv2.boxPoints(rect_1).astype(np.int0)
cv2.drawContours(img_cp, [box_0], 0, (0, 255, 0), 5)
_ = cv2.drawContours(img_cp, [box_1], 0, (0, 255, 0), 5)
plt.imshow(cv2.cvtColor(img_cp, cv2.COLOR_BGR2RGB))
plt.show()

# get the 2 points at two shortest borders
p = box_0[0]
min_dist = 100000
min_idx = -1
for i in range(1, box_0.shape[0]):
    if (box_0[i][0] - p[0])**2 + (box_0[i][1] - p[1])**2 < min_dist:
        min_idx = i
        min_dist = (box_0[i][0] - p[0])**2 + (box_0[i][1] - p[1])**2

cen_0 = [np.mean((box_0[min_idx][0], p[0])), np.mean((box_0[min_idx][1], p[1]))]
t_lst = list(range(4))
t_lst.remove(0)
t_lst.remove(min_idx)
cen_1 = [np.mean((box_0[t_lst[0]][0], box_0[t_lst[1]][0])), np.mean((box_0[t_lst[0]][1], box_0[t_lst[1]][1]))]

# Then we get the main direction
if not cen_1[0] - cen_0[0]:
    slope = 0
else:
    main_direction = (cen_1[1] - cen_0[1]) / (cen_1[0] - cen_0[0])
    if not cen_1[1] - cen_0[1]:
        # slope doesn't exist
        pass
    else:
        slope = 1/main_direction

# get sec_max_point
max_dist = 0
max_idx = -1
for i in range(1, box_0.shape[0]):
    if (box_0[i][0] - p[0])**2 + (box_0[i][1] - p[1])**2 > max_dist:
        max_idx = i
        max_dist = (box_0[i][0] - p[0])**2 + (box_0[i][1] - p[1])**2
sec_max_dist = 0
sec_max_idx = -1
tt_lst = list(range(4))
for i in range(1, box_0.shape[0]):
    if i == max_idx:
        continue
    if (box_0[i][0] - p[0])**2 + (box_0[i][1] - p[1])**2 > sec_max_dist:
        sec_max_idx = i
        sec_max_dist = (box_0[i][0] - p[0])**2 + (box_0[i][1] - p[1])**2
tt_lst.remove(0)
tt_lst.remove(sec_max_idx)

# draw cross lines
line1_points = [box_0[0], box_0[sec_max_idx]]
line1_middle = [int(np.mean((line1_points[0][0], line1_points[1][0]))),
                int(np.mean((line1_points[0][1], line1_points[1][1])))]
line2_points = [box_0[tt_lst[0]], box_0[tt_lst[1]]]
line2_middle = [int(np.mean ...
(more)
edit flag offensive delete link more
0

answered 2017-12-12 15:02:28 -0600

supra56 gravatar image

updated 2017-12-12 15:05:59 -0600

@Santhosh1. I want to measure the dimension of the objects in a image. Is that what you want to measured size? C:\fakepath\pen_box.jpg

I can do rectangle between two sides on ruler.

edit flag offensive delete link more

Comments

@supra56 Yes exactly what I am looking for, How did you remove the shadow part?

Santhosh1 gravatar imageSanthosh1 ( 2017-12-13 03:40:52 -0600 )edit

@Santhosh1. I didn't remove shadow. It is still exactly. Is that ur pen?

supra56 gravatar imagesupra56 ( 2017-12-13 06:42:39 -0600 )edit

@supra56 Its a challenge in itself, to detect an object in an image. Yeah it is my pen.

Santhosh1 gravatar imageSanthosh1 ( 2017-12-14 01:50:32 -0600 )edit

Can you tell me measurement of sizes(both pen and cover)? Preferably, inch, mm and cm

supra56 gravatar imagesupra56 ( 2017-12-14 06:30:46 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-12-12 03:28:29 -0600

Seen: 2,955 times

Last updated: Dec 13 '17