0

I am writing a program in Python to loop through images extracted from the frames of a video and detect lines within them. The images are of fairly poor quality and vary significantly in their content. Here are two examples: Sample Image 1 | Sample Image 2

I am trying to detect the lasers in each image and look at their angles. Eventually I would like to look at the distribution of these angles and output a sample of three of them.

In order to detect the lines in the images, I have looked at various combinations of the following:

  • Hough Lines
  • Canny Edge Detection
  • Bilateral / Gaussian Filtering
  • Denoising
  • Histogram Equalising
  • Morphological Transformations
  • Thresholding

I have tried lots of combinations of lots of different methods and I can't seem to come up with anything that really works. What I have been trying is along these lines:

import cv2
import numpy as np

img = cv2.imread('testimg.jpg')
grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
equal = clahe.apply(grey)

denoise = cv2.fastNlMeansDenoising(equal, 10, 10, 7, 21)

blurred = cv2.GaussianBlur(denoise, (3, 3), 0)
blurred = cv2.medianBlur(blurred, 9)

(mu, sigma) = cv2.meanStdDev(blurred)
edge = cv2.Canny(blurred, mu - sigma, mu + sigma)

lines = cv2.HoughLines(edge, 1, np.pi/180, 50)

if lines is not None:
    print len(lines[0])

    for rho,theta in lines[0]:
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))

        cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)

cv2.imshow("preview", img)
cv2.waitKey(0)

This is just one of many different attempts. Even if I can find a method that works slightly better for one of the images, it proves to be much worse for another one. I am not expecting completely perfect results, but I'm sure that they could be better than I've managed so far!

Could anyone suggest a tactic to help me move forward?

Richard
  • 1
  • 2
  • 1
    I'm voting to close this question as off-topic because it belongs on Signal Processing, http://dsp.stackexchange.com/ – wallyk Nov 27 '15 at 23:33
  • Example outputs ![Sample Image 1](https://i.imgur.com/BCYQUHX.jpg) ![Sample Image 2](https://i.imgur.com/STU8468.jpg) – Richard Nov 27 '15 at 23:35
  • 1
    I disagree that this is entirely signal processing (I'm fine if it moves, however...rules are rules). It's a very cool CV problem. Are your example outputs accurate? Is the camera position relative to the laser sources always the same? (ie. you have off image constant coords for the laser emitters?) – user1269942 Nov 28 '15 at 01:06
  • And. Is the length of the detected beams important? Or just the angle+spread? – user1269942 Nov 28 '15 at 01:08
  • Hi @user1269942 thanks for taking the time to look at my question. The camera is static - I had hoped that laser sources could perhaps be calculated by the off-image line intersections (but working on getting the lines before I worry about that...) The angles I am looking for are quite simple - I'm looking for the angles of the lines in the image. Length is not important. As you can see in the two sample outputs in my comment above, it is detecting lines quite accurately, but missing a lot. – Richard Nov 28 '15 at 08:52
  • OK, so the images are not all from the SAME laser setup? If it was, then you could grab a ruler and find the off-image coordinates of the laser(s). I know that doesn't help find the lines but knowing where the lines "come from" would help to know where to look...by chopping circular cutouts from the source image, applying a polar coordinate transform to make the lines parallel, then apply a few hand-made gabor filters (all horizontal but with different widths) or edge detection, find the maximum responses, note the position and back polar transform to get an angle(s). – user1269942 Nov 28 '15 at 22:19
  • Not knowing where the lasers are means you need to apply all sorts of angled edge detectors and it becomes a mess. – user1269942 Nov 28 '15 at 22:21
  • Do not expect to get anything useful from Sample Image 2. –  Dec 02 '15 at 13:14
  • Please show us the results that you expect, those images are too complex. –  Dec 02 '15 at 13:14

1 Answers1

1

Here is one answer. It is an answer that would help you if your camera is in a fixed position and so are your lasers...and your lasers emit from coordinates that you can determine. So, if you have many experiments that happen concurrently with the same setup, this can be a starting point.

The question image information along a polar coordinate system was helpful to get a polar transform. I chose not to use openCV because not everybody can get it going (windows). I took the code from the linked question and played around a bit. If you add his code to mine (without the imports or main method) then you'll have the required functions.

import numpy as np
import scipy as sp
import scipy.ndimage

import matplotlib.pyplot as plt
import sys

import Image

def main():

    data = np.array(Image.open('crop1.jpg').convert('LA').convert('RGB'))

    origin = (188, -30)
    polar_grid, r, theta = reproject_image_into_polar(data, origin=origin)

    means, angs = mean_move(polar_grid, 10, 5)
    means = np.array(means)
    means -= np.mean(means)
    means[means<0] = 0
    means *= means

    plt.figure()
    plt.bar(angs, means)
    plt.show()

def mean_move(data, width, stride):
  means = []
  angs = []
  x = 0
  while True:
    if x + width > data.shape[1]:
      break
    d = data[:,x:x+width]
    m =  np.mean(d[d!=0])
    means.append(m)
    ang = 180./data.shape[1] * float(x + x+width)/2.
    angs.append(ang)
    x += stride

  return means, angs

# copy-paste Joe Kington code here

Image around the upper source.

cropped image here

Notice that I chose one laser and cropped a region around its source. This can be done automatically and repeated for each image. I also estimated the source coordinates (188, -30) (in x,y form) based on where I thought it emitted from. Following image(a gimp screenshot!) shows my reasoning(it appeared that there was a very faint ray that I traced back too and took the intersection)...it also shows the measurement of the angle ~140 degrees.

enter image description here

polar transform of image(notice the vertical band if intensity...it is vertical because we chose the correct origin for the laser)

polar transform of image

And using a very hastily created moving window mean function and rough mapping to degree angles, along with a diff from mean + zeroing + squaring.

enter image description here

So your task becomes grabbing these peaks. Oh look ~140! Who's your daddy!

In recap, if the setup is fixed, then this may help you! I really need to get back to work and stop procrastinating.

Community
  • 1
  • 1
user1269942
  • 3,772
  • 23
  • 33
  • This looks really interesting - especially since it is a completely different way of looking at the problem. Since it's so new to me (and a little over my head) it will take me a while to play with it and fully understand it. Thank you so much for the thorough explanation too! Good luck with your work : ) – Richard Dec 01 '15 at 14:55