0

我正在用Python編寫一個程序來循環通過從視頻幀中提取的圖像並檢測其中的線條。圖像質量相當差,內容差異很大。這裏有兩個例子: Sample Image 1 | Sample Image 2使用Python檢測圖像中激光/光線的邊緣

我試圖檢測每個圖像中的激光並查看它們的角度。最終我想看看這些角度的分佈並輸出其中三個樣本。

爲了檢測在圖像中的線,我已經看過以下的各種組合:

  • 霍夫線
  • Canny邊緣檢測
  • 雙邊/高斯濾波
  • 去噪
  • 直方圖均衡
  • 形態轉換
  • 閾值處理

我已經嘗試了很多不同方法的組合,我似乎無法拿出任何真正有用的東西。我一直在嘗試沿着這些路線:

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) 

這只是許多不同嘗試之一。即使我能找到一種方法對於其中一幅圖像稍微好一點,但對另一幅圖像來說,它證明會更糟糕。我並不期待完美的結果,但我相信他們可能比我迄今爲止所做的更好!

任何人都可以提出一個策略來幫助我前進嗎?

+1

我投票結束這個題目,因爲它屬於信號處理,http://dsp.stackexchange.com/ – wallyk

+0

輸出示例![示例圖片1](https://i.imgur。 com/BCYQUHX.jpg)![示例圖片2](https://i.imgur.com/STU8468.jpg) – Richard

+1

我不同意這完全是信號處理(如果它移動,我很好,但是......規則是規則)。這是一個非常酷的簡歷問題。您的示例輸出是否準確?攝像機相對於激光源的位置是否始終相同? (即,你有激光發射器的圖像恆定座標?) – user1269942

回答

0

這裏有一個答案。如果您的相機處於固定位置,您的激光器以及您的激光器從您可以確定的座標中發射出來,這個答案將對您有所幫助。因此,如果您有許多實驗在同一設置中同時發生,那麼這可能是一個起點。

image information along a polar coordinate system這個問題對獲得極座標變換很有幫助。我選擇不使用openCV,因爲不是每個人都可以使用它(windows)。我從鏈接的問題中拿出了代碼並且玩了一下。如果你把他的代碼添加到我的(沒有導入或主要方法),那麼你將擁有所需的功能。

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 

圍繞上部源的圖像。

cropped image here

注意,我選擇一個激光器和裁剪圍繞其源的區域。這可以自動完成併爲每個圖像重複。我還根據我認爲它發出的位置估計了源座標(188,-30)(以x,y形式)。下面的圖片(一張gimp截圖!)顯示了我的推理(它似乎有一條非常微弱的光線,我也追溯到了這個交叉點)......它也顯示了角度的測量值〜140度。

enter image description here

極座標圖象的變換(注意垂直帶,如果強度...它是垂直的,因爲我們選擇了正確的產地爲激光)

polar transform of image

而且使用非常匆忙創建移動窗口意味着功能和粗糙的映射度角,與平均值的差異+歸零+現蕾一起。

enter image description here

所以,你的任務就變得抓住這些峯。哦,看〜140!你爸爸是誰!

回顧一下,如果設置是固定的,那麼這可能對您有所幫助!我真的需要回去工作,並停止拖延。

+0

這看起來非常有趣 - 特別是因爲它是一個完全不同的方式來看問題。由於它對我來說是如此的新鮮(我的頭腦還有一點點),我需要一段時間才能玩完它並充分理解它。非常感謝您的詳細解釋!祝你工作順利:) – Richard