Откриване на движение с OpenCV c++

Опитвам се да играя с моята уеб камера и OpenCV. Следвам този урок: http://mateuszstankiewicz.eu/?p=189. Но единственият резултат, който имам, е една червена рамка и не разбирам защо. Може ли някой да ми помогне да го оправя и да поправя това?

Ето моят код:

#include "mvt_detection.h"


Mvt_detection::Mvt_detection()
{

}

Mvt_detection::~Mvt_detection()
{
}

cv::Mat Mvt_detection::start(cv::Mat frame)
{
    cv::Mat back;
    cv::Mat fore;
    cv::BackgroundSubtractorMOG2 bg(5,3,true) ;
    cv::namedWindow("Background");
    std::vector<std::vector<cv::Point> > contours;

    bg.operator ()(frame,fore);
    bg.getBackgroundImage(back);
    cv::erode(fore,fore,cv::Mat());
    cv::dilate(fore,fore,cv::Mat());
    cv::findContours(fore,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
    cv::drawContours(frame,contours,-1,cv::Scalar(0,0,255),2);
    return frame;
}

Ето екранна снимка на това, което нашата камера връща: въведете описание на изображението тук

Опитах два други видеоклипа от там и там и има същия проблем.

Благодаря за помощта :).


person Lenjyco    schedule 20.01.2014    source източник
comment

Използвам JModelica за оптимизиране на модел, използвайки IPOPT във фонов режим.

Бих искал да изпълнявам много оптимизации паралелно. В момента правя това с помощта на мултипроцесорния модул.

В момента кодът е както следва. Той извършва сканиране на параметри върху променливите T и So и записва резултатите в изходни файлове, наречени за тези параметри. Изходните файлове също съдържат списък на параметрите, използвани в модела, заедно с резултатите от изпълнението.

#!/usr/local/jmodelica/bin/jm_python.sh
import itertools
import multiprocessing
import numpy as np
import time
import sys
import signal
import traceback
import StringIO
import random
import cPickle as pickle

def PrintResToFile(filename,result):
  def StripMX(x):
    return str(x).replace('MX(','').replace(')','')

  varstr = '#Variable Name={name: <10}, Unit={unit: <7}, Val={val: <10}, Col={col:< 5}, Comment="{comment}"\n'

  with open(filename,'w') as fout:
    #Print all variables at the top of the file, along with relevant information
    #about them.
    for var in result.model.getAllVariables():
      if not result.is_variable(var.getName()):
        val = result.initial(var.getName())
        col = -1
      else:
        val = "Varies"
        col = result.get_column(var.getName())

      unit = StripMX(var.getUnit())
      if not unit:
        unit = "X"

      fout.write(varstr.format(
        name    = var.getName(),
        unit    = unit,
        val     = val,
        col     = col,
        comment = StripMX(var.getAttribute('comment'))
      ))

    #Ensure that time variable is printed
    fout.write(varstr.format(
      name    = 'time',
      unit    = 's',
      val     = 'Varies',
      col     = 0,
      comment = 'None'
    ))

    #The data matrix contains only time-varying variables. So fetch all of
    #these, couple them in tuples with their column number, sort by column
    #number, and then extract the name of the variable again. This results in a
    #list of variable names which are guaranteed to be in the same order as the
    #data matrix.
    vkeys_in_order = [(result.get_column(x),x) for x in result.keys() if result.is_variable(x)]
    vkeys_in_order = map(lambda x: x[1], sorted(vkeys_in_order))

    for vk in vkeys_in_order:
      fout.write("{0:>13},".format(vk))
    fout.write("\n")

    sio = StringIO.StringIO()
    np.savetxt(sio, result.data_matrix, delimiter=',', fmt='%13.5f')
    fout.write(sio.getvalue())




def RunModel(params):
  T  = params[0]
  So = params[1]

  try:
    import pyjmi
    signal.signal(signal.SIGINT, signal.SIG_IGN)

    #For testing what happens if an error occurs
    # import random
    # if random.randint(0,100)<50:
      # raise "Test Exception"

    op = pyjmi.transfer_optimization_problem("ModelClass", "model.mop")
    op.set('a',        0.20)
    op.set('b',        1.00)
    op.set('f',        0.05)
    op.set('h',        0.05)
    op.set('S0',         So)
    op.set('finalTime',   T)

    # Set options, see: http://www.jmodelica.org/api-docs/usersguide/1.13.0/ch07s06.html
    opt_opts                                   = op.optimize_options()
    opt_opts['n_e']                            = 40
    opt_opts['IPOPT_options']['tol']           = 1e-10
    opt_opts['IPOPT_options']['output_file']   = '/z/err_'+str(T)+'_'+str(So)+'_info.dat'
    opt_opts['IPOPT_options']['linear_solver'] = 'ma27' #See: http://www.coin-or.org/Ipopt/documentation/node50.html

    res = op.optimize(options=opt_opts)

    result_file_name = 'out_'+str(T)+'_'+str(So)+'.dat'
    PrintResToFile(result_file_name, res)

    return (True,(T,So))
  except:
    ex_type, ex, tb = sys.exc_info()
    return (False,(T,So),traceback.extract_tb(tb))

try:
  fstatus = open('status','w')
except:
  print("Could not open status file!")
  sys.exit(-1)

T       = map(float,[10,20,30,40,50,60,70,80,90,100,110,120,130,140])
So      = np.arange(0.1,30.1,0.1)
tspairs = list(itertools.product(T,So))
random.shuffle(tspairs)

pool  = multiprocessing.Pool()
mapit = pool.imap_unordered(RunModel,tspairs)
pool.close()

completed = 0

while True:
  try:
    res = mapit.next(timeout=2)
    pickle.dump(res,fstatus)
    fstatus.flush()
    completed += 1
    print(res)
    print "{0: >4} of {1: >4} ({2: >4} left)".format(completed,len(tspairs),len(tspairs)-completed)
  except KeyboardInterrupt:
    pool.terminate()
    pool.join()
    sys.exit(0)
  except multiprocessing.TimeoutError:
    print "{0: >4} of {1: >4} ({2: >4} left)".format(completed,len(tspairs),len(tspairs)-completed)
  except StopIteration:
    break

Използване на модела:

optimization ModelClass(objective=-S(finalTime), startTime=0, finalTime=100)
  parameter Real S0 = 2;
  parameter Real F0 = 0;

  parameter Real a = 0.2;
  parameter Real b = 1;
  parameter Real f = 0.05;
  parameter Real h = 0.05;

  output Real F(start=F0, fixed=true, min=0, max=100, unit="kg");
  output Real S(start=S0, fixed=true, min=0, max=100, unit="kg");

  input Real u(min=0, max=1);
equation
  der(F) = u*(a*F+b);
  der(S) = f*F/(1+h*F)-u*(a*F+b);
end ModelClass;

Това безопасно ли е?

  -  person Micka    schedule 20.01.2014
comment
здравей, аз съм в същия проект (ние сме студенти и това е училищен проект). И се опитах да покажа изображението fore. Изображението е изцяло черно. И така, предполагам, че не можем да използваме този метод? Дали защото уеб камерата няма достатъчно качествен капацитет? Благодаря   -  person ogdabou    schedule 20.01.2014
comment
@Micka: Получавам бял прозорец, когато 3-тият аргумент на cv::BackgroundSubtractorMOG2 bg(5,3,true) ; е true и черен прозорец, когато е false   -  person Lenjyco    schedule 20.01.2014
comment
Най-лесният начин да направите това е да направите изображение на целия фон и след това да вземете абсолютната разлика между вашия фон и изображението с вас в него. Опитайте първо да видите дали можете да го накарате да работи.   -  person Dyrborg    schedule 20.01.2014
comment
@Dyrborg: bg.operator ()(frame,fore); не прави това?   -  person Lenjyco    schedule 20.01.2014
comment
Ако искате да приложите свое собствено извличане на преден план, можете да опитате ViBe vibeinmotion.com/Product/Literature. aspx Много е лесен за внедряване и доста добър, но патентован, така че не можете да го използвате за реални проекти ;)   -  person Micka    schedule 20.01.2014
comment
Не съм сигурен как работи с функциите на OpenCV. Когато направих това, просто използвах absdiff(InputArray назад, InputArray fore, OutputArray output). След това изходът показва точно къде е вашият движещ се обект.   -  person Dyrborg    schedule 20.01.2014
comment
Може също да помогне леко да замъглите всяко изображение, за да се отървете от шума от евтината уеб камера!   -  person Sebastian Schmitz    schedule 20.01.2014
comment
и двата примерни видеоклипа нямат (дори почти) постоянен фон, така че ще опитам някои примери от changedetection.net   -  person Micka    schedule 20.01.2014
comment
добре, има поне един проблем: отваряте камерата някъде другаде и извиквате start(cv::Mat frame) за всеки кадър? Ще бъде създаден нов backgroundSubtractor за всеки кадър, така че все още няма фон за изваждане от входното изображение.   -  person Micka    schedule 20.01.2014
comment
@Micka : Да, така е, опитах в друга версия да създам backgroundSubtractor на същото място, където отварям камерата и го подавам с cv::Mat frame, но все пак получих същия pb   -  person Lenjyco    schedule 20.01.2014
comment
@Micka: имам ли нужда от предишния кадър, за да направя фоновия субстрат?   -  person Lenjyco    schedule 20.01.2014
comment
ако кажете, че предишният кадър е вашият фонов модел, това би бил най-лесният метод за изваждане на фона и може да открие само текущи движения. За да го използвате, просто изчислете (frame - previous)>threshold. В противен случай: Тествайки малко с изображения от базата данни, BackgroundSubtractorMOG2 работи, но трябваше да коригирам параметрите (в противен случай много шумен преден план и твърде малка история), а фоновото изображение включваше нови изображения твърде бързо. Ако премахнете всички ерозиращи, разширяващи и контурни неща, също няма изображение на преден план? как изглежда вашето фоново изображение?   -  person Micka    schedule 20.01.2014
comment
Проблемът е отстранен, поставянето на BackgroundSubtractorMOG2 в полето на моя обект и инициализирането му в конструктора го кара да работи добре. TY всички за вноски.   -  person Lenjyco    schedule 20.01.2014
comment
това имах предвид по-рано! Споменахте, че сте опитали да го предоставите като параметър при извикване на функция, но там ще трябва да подадете параметъра by reference! Само за да разберете какво се обърка там.   -  person Micka    schedule 20.01.2014


Отговори (3)


Както каза @Lenjyco, ние решаваме проблема.

@Micka имаше добра идея:

Първо, BackgroundSubtractorMOG2 трябва да се инстанцира само ВЕДНЪЖ.

Ние го инстанцираме в конструктора и играем с историята и прага:

Mvt_detection::Mvt_detection()
{
    bg = new cv::BackgroundSubtractorMOG2(10, 16, false);
}

10 : номерът на изображението, към което се обръща назад за сравнение.

16: праговото ниво (размазване)

По този начин вече сме в състояние да откриваме движение.

Благодаря ти !

person ogdabou    schedule 22.01.2014

Използвах следния код, който е подобен на вашия и работи добре. Също така вземам входовете от моята уеб камера. Във вашия код не намерих imshow() и waitkey. Опитайте се да ги използвате. Моят код е следният:

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/video/background_segm.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdio.h>

#include <iostream>
#include <vector>

using namespace std;
using namespace cv;

int main()
{

    VideoCapture cap;
    bool update_bg_model = true;

    cap.open(0);
    cv::BackgroundSubtractorMOG2 bg;//(100, 3, 0.3, 5);
    bg.set ("nmixtures", 3);
    std::vector < std::vector < cv::Point > >contours;

    cv::namedWindow ("Frame");
    cv::namedWindow ("Background");

    Mat frame, fgmask, fgimg, backgroundImage;

    for(;;)
    {
        cap >> frame;
        bg.operator()(frame, fgimg);
        bg.getBackgroundImage (backgroundImage);
        cv::erode (fgimg, fgimg, cv::Mat ());
        cv::dilate (fgimg, fgimg, cv::Mat ());

        cv::findContours (fgimg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
        cv::drawContours (frame, contours, -1, cv::Scalar (0, 0, 255), 2);

        cv::imshow ("Frame", frame);
        cv::imshow ("Background", backgroundImage);


        char k = (char)waitKey(30);
        if( k == 27 ) break;

    }

    return 0;
}
person skm    schedule 20.01.2014
comment
Следвах вашия код. Но получих тази грешка.. ld: 1 дублиран символ за архитектура armv7 clang: грешка: командата за свързване е неуспешна с изходен код 1 (използвайте -v, за да видите извикването) - person Hussaan S; 23.07.2014

Проблемът е отстранен, поставянето на BackgroundSubtractorMOG2 в полето на моя обект и инициализирането му в конструктора го кара да работи добре.

person Lenjyco    schedule 21.01.2014