Richard
Richard

Reputation: 11

Detecting edges of lasers/lights in images using Python

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:

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?

Upvotes: 1

Views: 1822

Answers (1)

user1269942
user1269942

Reputation: 3852

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.

Upvotes: 1

Related Questions