1

I have this image:

original image

From that I want to detect only vertical lines, and don't want horizontal lines anyway.

I have written the following code which gives me this result with horizontal lines, too:

second image

That's my code:

import sys
import math
import cv2 as cv
import numpy as np


def main(argv):
    default_file = 'C:/Users/Rizwan/Desktop/amy_images/image2_43WqE0i.png'
    filename = argv[0] if len(argv) > 0 else default_file
    # Loads an image
    src = cv.imread(cv.samples.findFile(filename), cv.IMREAD_GRAYSCALE)
    img = cv.resize(src, (100, 40))
    src = cv.medianBlur(img, 5)
    # Check if image is loaded fine
    if src is None:
        print('Error opening image!')
        print('Usage: hough_lines.py [image_name -- default ' + default_file + '] \n')
        return -1

    dst = cv.Canny(src, 10, 40, None, 3)

    # Copy edges to the images that will display the results in BGR
    cdst = cv.cvtColor(dst, cv.COLOR_GRAY2BGR)
    cdstP = np.copy(cdst)

    lines = cv.HoughLines(dst, 1, np.pi / 180, 150, None, 0, 0)

    if lines is not None:
        for i in range(0, len(lines)):
            rho = lines[i][0][0]
            theta = lines[i][0][1]
            a = math.cos(theta)
            b = math.sin(theta)
            x0 = a * rho
            y0 = b * rho
            pt1 = (int(x0 + 1000 * (-b)), int(y0 + 1000 * (a)))
            pt2 = (int(x0 - 1000 * (-b)), int(y0 - 1000 * (a)))
            cv.line(cdst, pt1, pt2, (0, 0, 255), 3, cv.LINE_AA)

    linesP = cv.HoughLinesP(dst, 1, np.pi / 180, 50, None, 50, 10)

    if linesP is not None:
        for i in range(0, len(linesP)):
            l = linesP[i][0]
            cv.line(cdstP, (l[0], l[1]), (l[2], l[3]), (0, 0, 255), 3, cv.LINE_AA)

    cv.imshow("Source", src)
    cv.imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst)
    cv.imwrite("Source.png", cdst)
    cv.imwrite("Source1.png", src)
    # cv.imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP)

    cv.waitKey()
    return 0


if __name__ == "__main__":
    main(sys.argv[1:])

And one thing more that this gives me two lines in first-line and two lines in the second line as in original image there are only two thick lines but in the second image it giving me 4 vertical lines.

Any help would be highly appreciated.

1 Answer 1

3

The (intensity) difference between the lighter stripe and the background is just around 10. The best idea here would be to use cv2.adaptiveThreshold and morphological opening with some vertical line kernel afterwards, cf. cv2.morphologyEx.

Here's some code:

import cv2
import numpy as np
from skimage import io      # Only needed for web grabbing images, use cv2.imread for local images

# Read image from web (is already grayscale)
image = io.imread('https://i.sstatic.net/FVrCN.png')

# Apply adaptive threshold
image_thr = cv2.adaptiveThreshold(image, 255, cv2.THRESH_BINARY_INV, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 51, 0)

# Apply morphological opening with vertical line kernel
kernel = np.ones((image.shape[0], 1), dtype=np.uint8) * 255
image_mop = cv2.morphologyEx(image_thr, cv2.MORPH_OPEN, kernel)

# Canny edge detection
image_canny = cv2.Canny(image_mop, 1, 3)

# Get pixel values from the input image (force RGB/BGR on given input) within stripes
image_bgr = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
pixels = image_bgr[image_mop > 0, :]
print(pixels)

# (Visualization) Output
cv2.imshow('image', image)
cv2.imshow('image_thr', image_thr)
cv2.imshow('image_mop', image_mop)
cv2.imshow('image_canny', image_canny)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result of adaptive thresholding:

After thresholding

After morphological opening:

After opening

After Canny edge detection:

After Canny

You can play around with the parameters. Maybe the "shape" of the lines can be improved.

Hope that helps!

Sign up to request clarification or add additional context in comments.

10 Comments

Those cv2 skills :o
Thanks HansHirse for your reply, here is the error i get when running your code: ---> image_thr = cv2.adaptiveThreshold(image, 255, cv2.THRESH_BINARY_INV, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 51, 0) cv2.error: OpenCV(4.1.1) C:\projects\opencv-python\opencv\modules\imgproc\src\thresh.cpp:1645: error: (-215:Assertion failed) src.type() == CV_8UC1 in function 'cv::adaptiveThreshold'
@rizwan Make sure, that image is a uint8 grayscale image, i.e. image.shape should be (height, width). Most likely, you tried to pass a color image, i.e. image.shape is (height, width, 3). Try image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) before passing the image to cv2.adaptiveThreshold.
Yes, It solved. And the results are now even better than before. I am really thankful to you @HansHirse :) You really deserve more respect in the field :)
@HansHirse how can I get the original image's RGB values for the detect lines?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.