Reputation: 411
I am processing a large portion of images that are similar to the one below. I'd like to be able to calculate an average width of the black line (roughly the yellow line in the image), but am not sure how best to accomplish this in python. The yellow line itself is not present on the images, just the black bands.
The original image:
Upvotes: 0
Views: 189
Reputation: 8005
The first approach is using line-detector
.
Find the edges of your image
Detect the lines
lines = createFastLineDetector(_length_threshold=20).detect(canny_img)
Calculate the distance
for cur in lines:
(x1, y1, x2, y2) = cur[0]
dist = math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
print("Distance between ({:.2f}, {:.2f}) - ({:.2f}, {:.2f}) = {:.2f}"
.format(x1, y1, x2, y2, dist))
cv2.line(img, pt1=(x1, y1), pt2=(x2, y2), color=(0, 255, 0),
thickness=2)
cv2.imshow("detected", img)
cv2.waitKey(0)
Result
Update
If we apply the image-segmentation
we have to the following area:
The upper:
Distance between (118.06, 868.42) - (96.92, 871.40)
Distance between (95.94, 872.67) - (75.85, 876.11)
Distance between (74.88, 877.33) - (24.85, 886.16)
Distance between (23.96, 887.62) - (0.01, 890.06)
The lower:
Distance between (79.07, 894.60) - (99.02, 892.15)
Distance between (104.01, 886.54) - (125.99, 887.20)
Distance between (40.93, 901.45) - (66.05, 898.40)
Distance between (0.00, 906.02) - (33.99, 905.52)
If you randomly select two points: (66.05, 898.40)
and (24.85 - 886.16)
, the distance will be: 41.23
The solution is not perfect, but it might give an intuition for a better idea. Therefore I'm posting as an answer.
Code:
import cv2
import math
import numpy as np
from cv2.ximgproc import createFastLineDetector
img = cv2.imread('calculate_width.png')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray_img, 150, 255,
cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
kernel = np.ones((5, 5), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
sure_bg = cv2.dilate(opening, kernel)
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.3*dist_transform.max(),
255, 0)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
lines = createFastLineDetector(_length_threshold=20).detect(unknown)
for cur in lines:
(x1, y1, x2, y2) = cur[0]
dist = math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
print("Distance between ({:.2f}, {:.2f}) - ({:.2f}, {:.2f})"
.format(x1, y1, x2, y2))
cv2.line(img, pt1=(x1, y1), pt2=(x2, y2), color=(0, 255, 0),
thickness=2)
cv2.imshow("detected", img)
cv2.waitKey(0)
Upvotes: 1