OpenCV Multi view - eiichiromomma/CVMLAB GitHub Wiki

(OpenCV) Multi-view

C++ APIではROIをReleaseする必要が無いので,ROIを複数設定することで1つのウィンドウに結果を複数表示するのが簡単になった。

やりかた

  1. 作りたいマルチビュー画面の大きさのMatを作成(例では原画像の1/2のものを2x3で作成)
  2. 各々の位置にROI(実体はMat)を設定
  3. ROIへ画像をコピー(例ではResizeの出力先としているのでコピー不要)

出力画像例

大きめに作成して,数値を書き込むスペースのROIも確保すれば,より応用範囲が広がる。

サンプルソース

OpenCV Skeletonizationを使った処理で,filter2DをOpenMPによって並列処理させている。

    /*
    * Kasvand.cpp
    *
    *  Created on: 2011/03/03
    *      Author: Eiichiro Momma
    */
    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <vector>
    #include <iostream>
    #ifdef _OPENMP
    #include <omp.h>
    #endif
    
    using namespace cv;
    
    int main(void)
    {
    #ifdef _OPENMP
      std::cout<<"The number of processors is "<<omp_get_num_procs()<<std::endl;
      omp_set_num_threads(4);
    #endif
      float Smax=0;
      //Kasvandの反復型線検出オペレータ
      float L0[]={
        -1,-1,-1,-1,-1,
         0, 0, 0, 0, 0,
         2, 2, 2, 2, 2,
         0, 0, 0, 0, 0,
        -1,-1,-1,-1,-1
      };
      float L45[]={
         0,-1,-1, 0, 2,
        -1,-1, 0, 2, 0,
        -1, 0, 2, 0,-1,
         0, 2, 0,-1,-1,
         2, 0,-1,-1, 0
      };
      float L90[]={
        -1, 0, 2, 0,-1,
        -1, 0, 2, 0,-1,
        -1, 0, 2, 0,-1,
        -1, 0, 2, 0,-1,
        -1, 0, 2, 0,-1
      };
      float L135[]={
         2, 0,-1,-1, 0,
         0, 2, 0,-1,-1,
        -1, 0, 2, 0,-1,
        -1,-1, 0, 2, 0,
         0,-1,-1, 0, 2
      };
    
      VideoCapture cap;
      Mat frame, src;
      std::vector<Mat> planes;
      cap.open(0);
      if (!cap.isOpened())
        {
          std::cout << "Cap Failed" << std::endl;
          return 1;
        }
      cap >> frame;
      split(frame, planes);
      src = planes[2];
      Mat distsrc(src.rows, src.cols, CV_32FC1);
      Mat S00 = distsrc.clone();
      Mat S45 = distsrc.clone();
      Mat S90 = distsrc.clone();
      Mat S135 = distsrc.clone();
      Mat out = distsrc.clone();
    
      //canvas
      Mat fsrc = distsrc.clone();
      Mat canvas(src.rows*2/2, src.cols*3/2, CV_32FC1);
      //画像を割り振るROIの設定
      std::vector<Mat> vroi;
      vroi.push_back(canvas(Rect(0,0,src.cols/2, src.rows/2)));
      vroi.push_back(canvas(Rect((src.cols/2)*1, (src.rows/2)*0, src.cols/2, src.rows/2)));
      vroi.push_back(canvas(Rect((src.cols/2)*2, (src.rows/2)*0, src.cols/2, src.rows/2)));
      vroi.push_back(canvas(Rect((src.cols/2)*0, (src.rows/2)*1, src.cols/2, src.rows/2)));
      vroi.push_back(canvas(Rect((src.cols/2)*1, (src.rows/2)*1, src.cols/2, src.rows/2)));
      vroi.push_back(canvas(Rect((src.cols/2)*2, (src.rows/2)*1, src.cols/2, src.rows/2)));
    
      //kernelの作成
      const Mat kern00 = Mat(5, 5, CV_32FC1, L0).clone();
      const Mat kern45 = Mat(5, 5, CV_32FC1, L45).clone();
      const Mat kern90 = Mat(5, 5, CV_32FC1, L90).clone();
      const Mat kern135 = Mat(5, 5, CV_32FC1, L135).clone();
    
      namedWindow("canvas", CV_WINDOW_AUTOSIZE);
      int key = 0;
      while(key != 27)
        {
          cap >> frame;
          split(frame, planes);
          //他の処理に使いたい場合はframeやplanesをいじる
          //canvasはCV_32Fの1チャネルになっているので注意
          threshold(planes[2], src, 100, 255, CV_THRESH_BINARY);
          //距離変換
          distanceTransform(src, distsrc, CV_DIST_L2, 5);
          //フィルタ処理
    #ifdef _OPENMP
    #pragma omp parallel
    #pragma omp sections
          {
    #pragma omp section
            {
              filter2D(distsrc, S00, CV_32FC1, kern00);
            }
    #pragma omp section
            {
              filter2D(distsrc, S45, CV_32FC1, kern45);
            }
    #pragma omp section
            {
              filter2D(distsrc, S90, CV_32FC1, kern90);
            }
    #pragma omp section
            {
              filter2D(distsrc, S135, CV_32FC1, kern135);
            }
          }
    #else
          filter2D(distsrc, S00, CV_32FC1, kern00);
          filter2D(distsrc, S45, CV_32FC1, kern45);
          filter2D(distsrc, S90, CV_32FC1, kern90);
          filter2D(distsrc, S135, CV_32FC1, kern135);
    #endif
          //
          //Smax = MAX(S00,S45,S90,S135)
          //     / Smax, Smax >= 0
          // g = |
          //     \ 0 , others
          //
          for (int y=0; y < out.rows; y++)
            {
              for (int x=0; x< out.cols; x++)
                {
                  float tmp1 = (S00.at<float>(y, x) > S45.at<float>(y, x) )? S00.at<float>(y, x): S45.at<float>(y, x);
                  float tmp2 = (S90.at<float>(y, x) > S135.at<float>(y, x) )? S90.at<float>(y, x): S135.at<float>(y, x);
                  Smax = (tmp1 > tmp2)? tmp1: tmp2;
                  out.at<float>(y, x) = (Smax > 0)? Smax: 0.0;
                }
            }
          threshold(out, out, 7, 1, CV_THRESH_BINARY);
          src.convertTo(fsrc, CV_32FC1, 1.0/255, 0);
          resize(fsrc, vroi[0], vroi[0].size(), 0, 0, INTER_LINEAR);
          resize(S00, vroi[1], vroi[1].size(), 0, 0, INTER_LINEAR);
          resize(S45, vroi[2], vroi[2].size(), 0, 0, INTER_LINEAR);
          resize(out, vroi[3], vroi[3].size(), 0, 0, INTER_LINEAR);
          resize(S90, vroi[4], vroi[4].size(), 0, 0, INTER_LINEAR);
          resize(S135, vroi[5], vroi[5].size(), 0, 0, INTER_LINEAR);
          imshow("canvas", canvas);
          key = waitKey(33);
        }
      return 0;
    }

Python cv2の場合

最後は適当

import cv2
import numpy as np

L0 = np.array(
[-1,-1,-1,-1,-1,
0, 0, 0, 0, 0,
2, 2, 2, 2, 2,
0, 0, 0, 0, 0,
-1,-1,-1,-1,-1], np.float32).reshape(5,5)
L45 = np.array(
[0,-1,-1, 0, 2,
-1,-1, 0, 2, 0,
-1, 0, 2, 0,-1,
0, 2, 0,-1,-1,
2, 0,-1,-1, 0], np.float32).reshape(5,5)
L90 = np.array(
[-1, 0, 2, 0,-1,
-1, 0, 2, 0,-1,
-1, 0, 2, 0,-1,
-1, 0, 2, 0,-1,
-1, 0, 2, 0,-1], np.float32).reshape(5,5)
L135 = np.array(
[ 2, 0,-1,-1, 0,
0, 2, 0,-1,-1,
-1, 0, 2, 0,-1,
-1,-1, 0, 2, 0,
0,-1,-1, 0, 2], np.float32).reshape(5,5)


img1 = cv2.imread('sandbox/lena.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('Src',img1)
th, img2 = cv2.threshold(img1, 128, 255, cv2.THRESH_BINARY)
dimage = cv2.distanceTransform(img2, cv2.DIST_L2,5)
dimage = dimage/dimage.max()
cv2.imshow('dist',dimage)
R00 = cv2.filter2D(dimage, cv2.CV_32F, L0)
R45 = cv2.filter2D(dimage, cv2.CV_32F, L45)
R90 = cv2.filter2D(dimage, cv2.CV_32F, L90)
R135= cv2.filter2D(dimage, cv2.CV_32F, L135)
Racc = R00+R45+R90+R135
cv2.imshow('Result', Racc/Racc.max())
#MultiView
canvas = np.zeros([x*2 for x in img1.shape], dtype=np.float32 )
canvas[0:int(canvas.shape[0]/2), 0:int(canvas.shape[1]/2)] = img1/255.0
canvas[0:int(canvas.shape[0]/2), int(canvas.shape[1]/2):] = img2/255.0
canvas[int(canvas.shape[0]/2):, 0:int(canvas.shape[1]/2)] = dimage
canvas[int(canvas.shape[0]/2):, int(canvas.shape[1]/2):] = Racc/Racc.max()
cv2.imshow('multi',canvas)
cv2.waitKey(0)
cv2.destroyAllWindows()

動画像の場合 (Python)

特にやることは変わらない

import cv2
import numpy as np

L0 = np.array(
[-1,-1,-1,-1,-1,
0, 0, 0, 0, 0,
2, 2, 2, 2, 2,
0, 0, 0, 0, 0,
-1,-1,-1,-1,-1], np.float32).reshape(5,5)
L45 = np.array(
[0,-1,-1, 0, 2,
-1,-1, 0, 2, 0,
-1, 0, 2, 0,-1,
0, 2, 0,-1,-1,
2, 0,-1,-1, 0], np.float32).reshape(5,5)
L90 = np.array(
[-1, 0, 2, 0,-1,
-1, 0, 2, 0,-1,
-1, 0, 2, 0,-1,
-1, 0, 2, 0,-1,
-1, 0, 2, 0,-1], np.float32).reshape(5,5)
L135 = np.array(
[ 2, 0,-1,-1, 0,
0, 2, 0,-1,-1,
-1, 0, 2, 0,-1,
-1,-1, 0, 2, 0,
0,-1,-1, 0, 2], np.float32).reshape(5,5)

cap = cv2.VideoCapture(0)
key = 0
while key!=27:
    t, img1 = cap.read()
    img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    th, img2 = cv2.threshold(img1, 128, 255, cv2.THRESH_BINARY)
    dimage = cv2.distanceTransform(img2, cv2.DIST_L2,5)
    dimage = dimage/dimage.max()
    R00 = cv2.filter2D(dimage, cv2.CV_32F, L0)
    R45 = cv2.filter2D(dimage, cv2.CV_32F, L45)
    R90 = cv2.filter2D(dimage, cv2.CV_32F, L90)
    R135= cv2.filter2D(dimage, cv2.CV_32F, L135)
    Racc = R00+R45+R90+R135
    #MultiView
    canvas = np.zeros([x*2 for x in img1.shape], dtype=np.float32 )
    canvas[0:int(canvas.shape[0]/2), 0:int(canvas.shape[1]/2)] = img1/255.0
    canvas[0:int(canvas.shape[0]/2), int(canvas.shape[1]/2):] = img2/255.0
    canvas[int(canvas.shape[0]/2):, 0:int(canvas.shape[1]/2)] = dimage
    canvas[int(canvas.shape[0]/2):, int(canvas.shape[1]/2):] = Racc/Racc.max()
    cv2.imshow('multi',canvas)
    key = cv2.waitKey(10)
cv2.destroyAllWindows()
⚠️ **GitHub.com Fallback** ⚠️