4

I want to detect lines in an image which is at 45 degrees only with respect to the origin. I have to do it with 3x3 convolution only. I have solved it such that all lines at 45 degrees are removed and everything else stays(inverse of what I want). Any help in reaching from here to my final goal will be highly appreciated, thanks.

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


img = cv2.imread('Lines.png')

plt.imshow(img, cmap='gray')
plt.show()

kernel = np.array([[0, -1, 0],
                   [1, 0, 1],
                   [0, -1, 0]])

dst = cv2.filter2D(img, -1, kernel)
cv2.imwrite("filtered.png", dst)

This is the image before convolution:

enter image description here

This is the image after convolution:

This is what is happening right now

TylerH
  • 20,799
  • 66
  • 75
  • 101
Asim
  • 1,430
  • 1
  • 22
  • 43
  • Could you add the expected result? Based on the description, it is not 100% clear if you want only the edges or something else. – Berriel Feb 16 '19 at 12:45
  • I have edited the question, I want to detect line that is at 45 degrees with respect to the white centering origin. – Asim Feb 16 '19 at 12:58
  • This is still unclear. Please, add the expected result. What is the image you want as a result? Do you want only the edges of the rectangle that is +45º? Do you want the full (filled) rectangles that are both +45º and -45º? – Berriel Feb 16 '19 at 13:04
  • Sorry for still being unclear, I want all the lines removed except for the lines at 45 degrees. The very lines that have been removed by my convolution should stay and the one that are present right now should be removed. – Asim Feb 16 '19 at 13:06

2 Answers2

2

The filter I used is:

kernel = np.array([[0, -25, 1],
                   [-25, 5, -25],
                   [1, -25, 0]])

and the result was:

enter image description here

It wasn't perfect, but hope it helps.

Quang Hoang
  • 146,074
  • 10
  • 56
  • 74
  • How can I get the other line of 45 degrees? The one that will be perpendicular to this line. – Asim Feb 16 '19 at 13:53
  • Exchange the 0’s and 1’s? – Quang Hoang Feb 16 '19 at 13:55
  • Nope, the line perpendicular to this bright one line. There are 2, 45 degrees line in the figure that I gave, aren't there? – Asim Feb 16 '19 at 16:03
  • I told you @Asim, the question is not clear... I asked you if you want only the +45 or both + and -45. Looks like you want both. I still don't know if you want only the edges or the filled rectangle... – Berriel Feb 16 '19 at 17:57
  • @Berriel I want both. Just the lines and not edges. Both lines of +-45. – Asim Feb 16 '19 at 18:39
  • @Asim are you using lines meaning the rectangles? Anyway, you just need to add the **expected image output** and the question becomes crystal clear. – Berriel Feb 16 '19 at 18:54
  • 1
    @Asim When Quang suggested exchanging the 0's and 1's, that means in the kernel, not in the image, just in case that wasn't clear to you. – beaker Feb 16 '19 at 19:01
2

Well by the code you have provided in the question we obtained lines except those which we want to obtain. So we can take that and dilate it to fill the lines.

img = cv2.imread('lines.png')
kernel = np.array([[0, -1, 0],
                   [1, 0, 1],
                   [0, -1, 0]])

dst = cv2.filter2D(img, -1, kernel)
kernel = np.ones((5, 5), np.uint8)
dilated = cv2.dilate(dst, kernel, iterations = 1)

dilated lines

Then we need to remove the dots above the lines at 45 degrees so we use morphological opening for that and threshold the image to convert all the lines to pixel values=255.

kernel = np.ones((7, 7), np.uint8)
opening = cv2.morphologyEx(dilated, cv2.MORPH_OPEN, kernel)
_,thresh = cv2.threshold(opening,10,255,cv2.THRESH_BINARY)

filled and thresholded

Then using cv2.bitwise_and of original image and cv2.bitwise_not of the threshold obtained we obtain our lines.

res = cv2.bitwise_and(img, cv2.bitwise_not(thresh))

intermediate result

We obtain the lines but we need to remove the circle in the middle. For that we use cv2.erode on the original image to obtain only the middle circle, threshold it and then again use cv2.bitwise_and and cv2.bitwise_not to remove it from res.

kernel = np.ones((7, 7), np.uint8)
other = cv2.erode(img, kernel, iterations = 1)
_,thresh = cv2.threshold(other,10,255,cv2.THRESH_BINARY)
result = cv2.bitwise_and(res, cv2.bitwise_not(thresh))
cv2.imshow("Image", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Final result

Vardan Agarwal
  • 2,023
  • 2
  • 15
  • 27