2016-07-21 25 views
0

パッシブステレオカメラシステムからの視差行列に基づいて、私はOpenCVによる障害検出のためにv視差表現を計算する必要があります。OpenCV関数によるV視差の高速計算calcHist

動作実装はではなく、です。問題はそれを速くすることです...

(1)v-Disparityのリファレンス:Labayrade、R. and Aubert、D. and Tarel、JPRealステレオビジョンにおけるステレオビジョンでの障害検出は、視差表現

短い塩基性、V視差(図1)、ディスパリティ・マトリックス(図2)の行を分析AN視差値上行ごとにヒストグラムとして結果を表すことであるを取得します。 u-視差(図3)は、視差 - 行列の列で同じです。 (すべての図は偽色です)

私はPythonとC++で "same"を実装しています。 Pythonの速度は許容されますが、C++では、私はuとvの視差を約0.5秒(0.5秒)にします。

(1.編集:別の時間測定に、U-ヒストグラムの算出のみが時間の大容量を...要するため):

これは、次の質問に私をリード

  1. ヒストグラムの線ワイズ計算のループを回避できますか? calcHist -Function from OpenCVの1回の呼び出しでそれを行う "トリック"はありますか?おそらく次元?

  2. これはC++でコード化されているだけで、実行時の問題は計算に使用されるループと関係がありませんか?

おかげで、Pythonではすべての


作業を実装:C++での

#!/usr/bin/env python2 
#-*- coding: utf-8 -*- 
# 
# THIS SOURCE-CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
# IMPLIED. IN NO EVENT WILL THE AUTHOR BE HELD LIABLE FOR ANY DAMAGES ARISING FROM 
# THE USE OF THIS SOURCE-CODE. USE AT YOUR OWN RISK. 

import cv2 
import numpy as np 
import time 

def draw_object(image, x, y, width=50, height=100): 
    color = image[y, x] 
    image[y-height:y, x-width//2:x+width//2] = color 


IMAGE_HEIGHT = 600 
IMAGE_WIDTH = 800 

while True: 

    max_disp = 200 

    # create fake disparity 
    image = np.zeros((IMAGE_HEIGHT, IMAGE_WIDTH), np.uint8) 

    for c in range(IMAGE_HEIGHT)[::-1]: 
     image[c, ...] = int(float(c)/IMAGE_HEIGHT * max_disp) 

    draw_object(image, 275, 175) 
    draw_object(image, 300, 200) 
    draw_object(image, 100, 350) 

    # calculate v-disparity 
    vhist_vis = np.zeros((IMAGE_HEIGHT, max_disp), np.float) 
    for i in range(IMAGE_HEIGHT): 
     vhist_vis[i, ...] = cv2.calcHist(images=[image[i, ...]], channels=[0], mask=None, histSize=[max_disp], 
             ranges=[0, max_disp]).flatten()/float(IMAGE_HEIGHT) 


    vhist_vis = np.array(vhist_vis * 255, np.uint8) 
    vblack_mask = vhist_vis < 5 
    vhist_vis = cv2.applyColorMap(vhist_vis, cv2.COLORMAP_JET) 
    vhist_vis[vblack_mask] = 0 

    # calculate u-disparity 
    uhist_vis = np.zeros((max_disp, IMAGE_WIDTH), np.float) 
    for i in range(IMAGE_WIDTH): 
     uhist_vis[..., i] = cv2.calcHist(images=[image[..., i]], channels=[0], mask=None, histSize=[max_disp], 
             ranges=[0, max_disp]).flatten()/float(IMAGE_WIDTH) 

    uhist_vis = np.array(uhist_vis * 255, np.uint8) 
    ublack_mask = uhist_vis < 5 
    uhist_vis = cv2.applyColorMap(uhist_vis, cv2.COLORMAP_JET) 
    uhist_vis[ublack_mask] = 0 


    image = cv2.applyColorMap(image, cv2.COLORMAP_JET) 


    cv2.imshow('image', image) 

    cv2.imshow('vhist_vis', vhist_vis) 
    cv2.imshow('uhist_vis', uhist_vis) 

    cv2.imwrite('disparity_image.png', image) 
    cv2.imwrite('v-disparity.png', vhist_vis) 
    cv2.imwrite('u-disparity.png', uhist_vis) 


    if chr(cv2.waitKey(0)&255) == 'q': 
     break 

作業を実装:

#include <iostream> 
#include <stdlib.h> 

#include <ctime> 

#include <opencv2/opencv.hpp> 


using namespace std; 

void draw_object(cv::Mat image, unsigned int x, unsigned int y, unsigned int width=50, unsigned int height=100) 
{ 
    image(cv::Range(y-height, y), cv::Range(x-width/2, x+width/2)) = image.at<unsigned char>(y, x); 
} 


int main() 
{ 
    unsigned int IMAGE_HEIGHT = 600; 
    unsigned int IMAGE_WIDTH = 800; 
    unsigned int MAX_DISP = 250; 
    unsigned int CYCLE = 0; 

    //setenv("QT_GRAPHICSSYSTEM", "native", 1); 


    // === PREPERATIONS == 
    cv::Mat image = cv::Mat::zeros(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8U); 
    cv::Mat uhist = cv::Mat::zeros(IMAGE_HEIGHT, MAX_DISP, CV_32F); 
    cv::Mat vhist = cv::Mat::zeros(MAX_DISP, IMAGE_WIDTH, CV_32F); 

    cv::Mat tmpImageMat, tmpHistMat; 

    float value_ranges[] = {(float)0, (float)MAX_DISP}; 
    const float* hist_ranges[] = {value_ranges}; 
    int channels[] = {0}; 
    int histSize[] = {MAX_DISP}; 


    struct timespec start, finish; 
    double elapsed; 

    while(1) 
    { 
     CYCLE++; 

     // === CLEANUP == 
     image = cv::Mat::zeros(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8U); 
     uhist = cv::Mat::zeros(IMAGE_HEIGHT, MAX_DISP, CV_32F); 
     vhist = cv::Mat::zeros(MAX_DISP, IMAGE_WIDTH, CV_32F); 

     // === CREATE FAKE DISPARITY WITH OBJECTS === 
     for(int i = 0; i < IMAGE_HEIGHT; i++) 
      image.row(i) = ((float)i/IMAGE_HEIGHT * MAX_DISP); 

     draw_object(image, 200, 500); 
     draw_object(image, 525 + CYCLE%100, 275); 
     draw_object(image, 500, 300 + CYCLE%100); 

     clock_gettime(CLOCK_MONOTONIC, &start); 

     // === CALCULATE V-HIST === 
     for(int i = 0; i < IMAGE_HEIGHT; i++) 
     { 
      tmpImageMat = image.row(i); 
      vhist.row(i).copyTo(tmpHistMat); 

      cv::calcHist(&tmpImageMat, 1, channels, cv::Mat(), tmpHistMat, 1, histSize, hist_ranges, true, false); 

      vhist.row(i) = tmpHistMat.t()/(float) IMAGE_HEIGHT; 
     } 

     clock_gettime(CLOCK_MONOTONIC, &finish); 
     elapsed = (finish.tv_sec - start.tv_sec); 
     elapsed += (finish.tv_nsec - start.tv_nsec) * 1e-9; 
     cout << "V-HIST-TIME: " << elapsed << endl; 

     clock_gettime(CLOCK_MONOTONIC, &start); 

     // === CALCULATE U-HIST === 
     for(int i = 0; i < IMAGE_WIDTH; i++) 
     { 
      tmpImageMat = image.col(i); 
      uhist.col(i).copyTo(tmpHistMat); 

      cv::calcHist(&tmpImageMat, 1, channels, cv::Mat(), tmpHistMat, 1, histSize, hist_ranges, true, false); 

      uhist.col(i) = tmpHistMat/(float) IMAGE_WIDTH; 
     } 

     clock_gettime(CLOCK_MONOTONIC, &finish); 
     elapsed = (finish.tv_sec - start.tv_sec); 
     elapsed += (finish.tv_nsec - start.tv_nsec) * 1e-9; 
     cout << "U-HIST-TIME: " << elapsed << endl; 

     // === PREPARE AND SHOW RESULTS === 

     uhist.convertTo(uhist, CV_8U, 255); 
     cv::applyColorMap(uhist, uhist, cv::COLORMAP_JET); 

     vhist.convertTo(vhist, CV_8U, 255); 
     cv::applyColorMap(vhist, vhist, cv::COLORMAP_JET); 

     cv::imshow("image", image); 
     cv::imshow("uhist", uhist); 
     cv::imshow("vhist", vhist); 



     if ((cv::waitKey(1)&255) == 'q') 
      break; 
    } 

    return 0; 
} 

enter image description here 図1:V-視差

fake disparity matrix 図2:偽視差マトリックス

enter image description here 図3:U視差


  1. 編集:
      C言語で、UとV-格差と個別の時間測定のための
    • 正しい名前++例
    • 小さなタイプミス

答えて

0

今日は、私は、問題を再検討する可能性を持っていました。 Mat構造のOpenCVの基礎(1)と、1回の計算に膨大な時間がかかることを覚えていれば、私は解決策がありました。

OpenCVでは、画像の各行に行ポインタで到達することができました。私は、OpenCVは、ヒストグラムを構築するために、すべての行ポインタ+列オフセットを解決する必要があると考えています(u視差計算で行われた)。

OpenCVが行ポインタを使用できるようにコードを変更すると、問題が解決されます。私は画像を転置し、ループ後の動作を逆U字HIST-forループだから

  | old code [s] | changed [s] 
------------+--------------+------------- 
V-HIST-TIME | 0.00351909 | 0.00334152 
U-HIST-TIME | 0.600039  | 0.00449285 

。計算のための行別のアクセスは、今度は行ポインタを介して行うことができます。

変更コードライン:

 // === CALCULATE U-HIST === 
     image = image.t(); 
     for(int i = 0; i < IMAGE_WIDTH; i++) 
     { 
      tmpImageMat = image.row(i); 
      uhist.col(i).copyTo(tmpHistMat); 

      cv::calcHist(&tmpImageMat, 1, channels, cv::Mat(), tmpHistMat, 1, histSize, hist_ranges, true, false); 

      uhist.col(i) = tmpHistMat/(float) IMAGE_WIDTH; 
     } 
     image = image.t(); 

最後に、私の2番目の質問が有効になり、ランタイムの問題はループにない属します。 5ミリ秒未満の時間は(今のところ)十分速いです。

0

非常に良いコードと非常に説明しています。それは私の視差を理解する助けになりました。ただし、C/C++コードが壊れています。私はこのコードで彼を修正した:

cv::Mat uhist = cv::Mat::zeros(MAX_DISP, IMAGE_WIDTH, CV_32F); 
cv::Mat vhist = cv::Mat::zeros(IMAGE_WIDTH, MAX_DISP, CV_32F); 
関連する問題