While loop for Kairos to only capture every 1 minute

52 Views Asked by At

I am currently using a facial-recognition software called Kairos to analyze emotions of a crowd on a video.

My question is, instead of using "true" in while (which will analyze crowd emotions every second), how do I configure it in such a way that it only analyzes the crowd every 1 minute? Thanks in advance.

HumanAnalysisService has = null;

try{
    has = new HumanAnalysisService("license.xml", "", 20, 4);
} catch (ApplicationException lie) {
    Console.WriteLine(lie.Message);
    return;
}

// has = new HumanAnalysisService("license.xml", "", 20, 4);

/* attach to camera device */
// has.initUsingCameraSource(0);
has.initUsingImageSource(file1);

/* *loop thru the capture feed */
while (true) {
    /* pull pull out the next frame */
    has.pullFrame();

    /* does the device have more frames */
    if (has.isFrameEmpty())
        break;

    /* process the pulled frame */
    has.processFrame();

    /* get the people that are in the current frame*/
    People people = has.getPeople();

    System.Console.Write("Media Height: " + has.getMediaSourceHeight());
    System.Console.Write("Media Width: " + has.getMediaSourceWidth());
    System.Console.Write("Media Type: " + has.getMediaType());
    System.Console.Write("Mime Type: " + has.getMediaContentType() + "\n\n");

    /* print out the info from every person in te frame*/
    // foreach ( Person person in people )
        for (int i = 0; i < people.size(); i++) {
            System.Console.Write("Person id" + people.get(i).id + " , face x coordinate: " + people.get(i).face.x + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , face y coordinate: " + people.get(i).face.x + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , face width coordinate: " + people.get(i).face.width + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , face height coordinate: " + people.get(i).face.height + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , Emotion - Joy: " + people.get(i).impression.emotion_response.joy_score + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , Emotion - Surprise: " + people.get(i).impression.emotion_response.surprise_score + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , Emotion - Anger: " + people.get(i).impression.emotion_response.anger_score + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , Emotion - Fear: " + people.get(i).impression.emotion_response.fear_score + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , Emotion - Sadness: " + people.get(i).impression.emotion_response.sadness_score + "\n");
            System.Console.Write("Person id" + people.get(i).id + " , Emotion - Disgust: " + people.get(i).impression.emotion_response.disgust_score + "\n");
        }
    }
}
2

There are 2 best solutions below

1
Enigmativity On BEST ANSWER

I'd suggest using either a Timer:

var timer = new System.Timers.Timer()
timer.Interval = 60000;
timer.Elapsed += (_s, _e) =>
{
    /* pull pull out the next frame */
    has.pullFrame();

    /* does the device have more frames */
    if (has.isFrameEmpty())
        timer.Enabled = false;;

    // REST OF YOUR LOOP CODE HERE
};
timer.Enabled = true;

Or use Microsoft Reactive Framework:

IDisposable subscription =
    Observable
        .Interval(TimeSpan.FromMinutes(1.0))
        .Do(x => has.pullFrame())
        .TakeWhile(n => !has.isFrameEmpty())
        .Do(x =>
        {
            /* process the pulled frame */
            has.processFrame();

            /* get the people that are in the current frame*/
            People people = has.getPeople();

            // REST OF YOUR LOOP CODE HERE
        })
        .Wait();

For this latter option just NuGet "System.Reactive" and add using System.Reactive.Linq; to your code.

0
dariogriffo On

It might be over killing for your app, but take a look at Quartz.Net You can simply create a task to repeat indefinitely. Clean code that you can easily test

[DisallowConcurrentExecution]
public class CaptureFeedFeedbackLoop : IJob
{
    public static HumanAnalysisService Has;

    public Task Execute(IJobExecutionContext context)
    {
        //Do stuff
        return Task.CompletedTask;
    }
}

and then

HumanAnalysisService has = null;

try
{
    has = new HumanAnalysisService("license.xml", "", 20, 4);
} 
catch (ApplicationException lie)
{
    Console.WriteLine(lie.Message);
    return;
}

// has = new HumanAnalysisService("license.xml", "", 20, 4);

/* attach to camera device */
// has.initUsingCameraSource(0);
has.initUsingImageSource(file1);
IJobDetail job = JobBuilder.Create<CaptureFeedFeedbackLoopJob>().WithIdentity("job1", "group1").Build();

ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x
    .WithIntervalInSeconds(60)
    .RepeatForever())
.Build();


await scheduler.ScheduleJob(job, trigger);

If you need sync version of the methods you can use Quartz.net 2.x