ZZZZZBON
ZZZZZBON

Reputation: 21

How to count lines in an image with python, openCV

I want to count paper, so I am thinking about using line detection. I have tried some methods like Canny, HoughLines, and FLD. But I only get the processed photo. I have no idea how to count it. There are some small line segments that are the lines we want. I have used len(lines) or len(contours). However, the result is far from what I expected. The result is a hundred or thousand. So, does anyone have any suggestions?

The original photo:

the original photo

Processd by Canny:

processd by Canny

Processed by LSD:

processed by LSD

Processed by HoughLinesP:

processed by HoughLinesP

#Canny
samplename = "sam04.jpg"
img = cv2.imread('D:\\Users\\Administrator\\PycharmProjects\\EdgeDetect\\venv\\sample\\{}'.format(samplename),0)

edges = cv2.Canny(img,100,200)
cv2.imwrite('.\\detected\\{}'.format("p03_"+samplename),edges)
plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()
#LSD
samplename = "sam09.jpg"

img0 = cv2.imread('D:\\Users\\Administrator\\PycharmProjects\\EdgeDetect\\venv\\sample\\{}'.format(samplename))

img = cv2.cvtColor(img0,cv2.COLOR_BGR2GRAY)


fld = cv2.ximgproc.createFastLineDetector()

dlines = fld.detect(img)


# drawn_img = fld.drawSegments(img0,dlines, )
for dline in dlines:
    x0 = int(round(dline[0][0]))
    y0 = int(round(dline[0][1]))
    x1 = int(round(dline[0][2]))
    y1 = int(round(dline[0][3]))
    cv2.line(img0, (x0, y0), (x1,y1), (0,255,0), 1, cv2.LINE_AA)


cv2.imwrite('.\\detected\\{}'.format("p12_"+samplename), img0)
cv2.imshow("LSD", img0)
cv2.waitKey(0)
cv2.destroyAllWindows()
#HoughLine
import cv2
import numpy as np
samplename = "sam09.jpg"

#First, get the gray image and process GaussianBlur.
img = cv2.imread('D:\\Users\\Administrator\\PycharmProjects\\EdgeDetect\\venv\\sample\\{}'.format(samplename))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)

#Second, process edge detection use Canny.
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
cv2.imshow('photo2',edges)
cv2.waitKey(0)
#Then, use HoughLinesP to get the lines. You can adjust the parameters for better performance.

rho = 1  # distance resolution in pixels of the Hough grid
theta = np.pi / 180  # angular resolution in radians of the Hough grid
threshold = 15  # minimum number of votes (intersections in Hough grid cell)
min_line_length = 50  # minimum number of pixels making up a line
max_line_gap = 20  # maximum gap in pixels between connectable line segments
line_image = np.copy(img) * 0  # creating a blank to draw lines on

# Run Hough on edge detected image
# Output "lines" is an array containing endpoints of detected line segments
lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),
                    min_line_length, max_line_gap)
print(lines)
print(len(lines))
for line in lines:
    for x1,y1,x2,y2 in line:
        cv2.line(line_image,(x1,y1),(x2,y2 ),(255,0,0),5)

#Finally, draw the lines on your srcImage.
# Draw the lines on the  image
lines_edges = cv2.addWeighted(img, 0.8, line_image, 1, 0)
cv2.imshow('photo',lines_edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('.\\detected\\{}'.format("p14_"+samplename),lines_edges)

Upvotes: 2

Views: 3858

Answers (1)

Khalid
Khalid

Reputation: 41

I think you could count the number of lines (papers) based on how many straight lines do you have. My idea is that

  1. You should calculate the distances for all points that you get from HoughLinesP by using np.linalg.norm(point1 - point2) for more details.
  2. Then you could adjust the proper distance that used to identify the lines to ignore the noise (small) lines. I recommend using min_line_length in HoughLinesP.
  3. Count the number of distances (lines) that are bigger than the proper distance.

This is the code that I used for your image:

image

# After you apply Hough on edge detected image
lines = cv.HoughLinesP(img, rho, theta, threshold, np.array([]),
                    min_line_length, max_line_gap)

# calculate the distances between points (x1,y1), (x2,y2) :

distance = []
for line in lines:
    distance.append(np.linalg.norm(line[:,:2] - line[:,2:]))

print('max distance:',max(distance),'\nmin distance:',min(distance))

# Adjusting the best distance 
bestDistance=1110

numberOfLines=[]
count=0
for x in distance:
    if x>bestDistance:
        numberOfLines.append(x)
        count=count+1

print('Number of lines:',count)

Output:

max distance: 1352.8166912039487 
min distance: 50.0
Number of lines: 17

Upvotes: 2

Related Questions