/*
Copyright (C) 2022 Lari Varjonen <[email protected]>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "frames_extractor.h"
void FramesExtractor::run()
{
if (cap == nullptr)
{
qCritical() << "cap == nullptr";
return;
}
if(!cap->isOpened())
{
qCritical() << "Video file is invalid.";
return;
}
emit set_max(frames_wanted);
video_frame_count = cap->get(cv::CAP_PROP_FRAME_COUNT);
if (start_frame > end_frame && end_frame < start_frame)
{
return;
}
if (frames_wanted == 1 || start_frame == end_frame)
{
save_one_frame(start_frame+1, 1);
emit set_value(frames_wanted, start_frame+1, start_frame+1);
emit process_done();
return;
}
if (end_frame > video_frame_count)
{
end_frame = video_frame_count;
}
if (start_frame > 0)
{
start_frame += 1;
}
double frame_step = (end_frame - start_frame) / frames_wanted;
double current_frame = start_frame;
unsigned int frame_number = 1;
for(unsigned int i = 0; i < frames_wanted && current_frame <= end_frame;)
{
emit set_value(i, current_frame, end_frame);
if (!running)
{
break;
}
if (i == frames_wanted-1)
{
current_frame = (end_frame==video_frame_count)?end_frame-1:end_frame+1;
}
save_one_frame(current_frame, frame_number);
i++;
current_frame = start_frame + (i * frame_step);
frame_number++;
}
if (running)
{
emit process_done();
}
}
void FramesExtractor::save_one_frame(double current_frame,
int frame_number)
{
cv::Mat frame;
cap->set(cv::CAP_PROP_POS_FRAMES, current_frame);
*cap >> frame;
int i = 1;
while (frame.empty())
{
if (i == max_frames_to_backtrack)
{
qCritical() << tr("Unable to read a frame: %1 %2 %3")
.arg(current_frame)
.arg(frame_number)
.arg(video_frame_count);
return;
}
i++;
current_frame--;
cap->set(cv::CAP_PROP_POS_FRAMES, current_frame);
*cap >> frame;
}
double current_frame_secs = current_frame / video_fps;
QTime a(0,0,0);
a = a.addSecs(current_frame_secs);
QString time = a.toString();
QString file_path = out_dir_path;
file_path += QString::number(frame_number);
file_path += QString("[") + time + "].jpg";
std::vector<int> params;
params.push_back(cv::IMWRITE_JPEG_QUALITY);
params.push_back(100);
imwrite(file_path.toStdString(), frame, params);
}
bool FramesExtractor::set_video(QString file_path)
{
cv::VideoCapture cap0(file_path.toStdString());
if (!cap0.isOpened() || cap0.get(cv::CAP_PROP_FRAME_COUNT) <= 1)
{
return true;
}
delete cap;
cap = new cv::VideoCapture(file_path.toStdString());
return false;
}
int FramesExtractor::get_video_frame_count()
{
return cap->get(cv::CAP_PROP_FRAME_COUNT);
}
double FramesExtractor::get_video_fps()
{
return cap->get(cv::CAP_PROP_FPS);
}
/* Copyright (C) 2022 Lari Varjonen <[email protected]> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "frames_extractor.h" void FramesExtractor::run() { if (cap == nullptr) { qCritical() << "cap == nullptr"; return; } if(!cap->isOpened()) { qCritical() << "Video file is invalid."; return; } emit set_max(frames_wanted); video_frame_count = cap->get(cv::CAP_PROP_FRAME_COUNT); if (start_frame > end_frame && end_frame < start_frame) { return; } if (frames_wanted == 1 || start_frame == end_frame) { save_one_frame(start_frame+1, 1); emit set_value(frames_wanted, start_frame+1, start_frame+1); emit process_done(); return; } if (end_frame > video_frame_count) { end_frame = video_frame_count; } if (start_frame > 0) { start_frame += 1; } double frame_step = (end_frame - start_frame) / frames_wanted; double current_frame = start_frame; unsigned int frame_number = 1; for(unsigned int i = 0; i < frames_wanted && current_frame <= end_frame;) { emit set_value(i, current_frame, end_frame); if (!running) { break; } if (i == frames_wanted-1) { current_frame = (end_frame==video_frame_count)?end_frame-1:end_frame+1; } save_one_frame(current_frame, frame_number); i++; current_frame = start_frame + (i * frame_step); frame_number++; } if (running) { emit process_done(); } } void FramesExtractor::save_one_frame(double current_frame, int frame_number) { cv::Mat frame; cap->set(cv::CAP_PROP_POS_FRAMES, current_frame); *cap >> frame; int i = 1; while (frame.empty()) { if (i == max_frames_to_backtrack) { qCritical() << tr("Unable to read a frame: %1 %2 %3") .arg(current_frame) .arg(frame_number) .arg(video_frame_count); return; } i++; current_frame--; cap->set(cv::CAP_PROP_POS_FRAMES, current_frame); *cap >> frame; } double current_frame_secs = current_frame / video_fps; QTime a(0,0,0); a = a.addSecs(current_frame_secs); QString time = a.toString(); QString file_path = out_dir_path; file_path += QString::number(frame_number); file_path += QString("[") + time + "].jpg"; std::vector<int> params; params.push_back(cv::IMWRITE_JPEG_QUALITY); params.push_back(100); imwrite(file_path.toStdString(), frame, params); } bool FramesExtractor::set_video(QString file_path) { cv::VideoCapture cap0(file_path.toStdString()); if (!cap0.isOpened() || cap0.get(cv::CAP_PROP_FRAME_COUNT) <= 1) { return true; } delete cap; cap = new cv::VideoCapture(file_path.toStdString()); return false; } int FramesExtractor::get_video_frame_count() { return cap->get(cv::CAP_PROP_FRAME_COUNT); } double FramesExtractor::get_video_fps() { return cap->get(cv::CAP_PROP_FPS); }
/*
    Copyright (C) 2022 Lari Varjonen <[email protected]>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "frames_extractor.h"


void FramesExtractor::run()
{
    if (cap == nullptr)
    {
        qCritical() << "cap == nullptr";
        return;
    }
    if(!cap->isOpened())
    {
        qCritical() << "Video file is invalid.";
        return;
    }

    emit set_max(frames_wanted);
    video_frame_count = cap->get(cv::CAP_PROP_FRAME_COUNT);

    if (start_frame > end_frame && end_frame < start_frame)
    {
        return;
    }

    if (frames_wanted == 1 || start_frame == end_frame)
    {
        save_one_frame(start_frame+1, 1);
        emit set_value(frames_wanted, start_frame+1, start_frame+1);
        emit process_done();
        return;
    }

    if (end_frame > video_frame_count)
    {
        end_frame = video_frame_count;
    }
    if (start_frame > 0)
    {
        start_frame += 1;
    }

    double frame_step = (end_frame - start_frame) / frames_wanted;
    double current_frame = start_frame;
    unsigned int frame_number = 1;

    for(unsigned int i = 0; i < frames_wanted && current_frame <= end_frame;)
    {
        emit set_value(i, current_frame, end_frame);
        if (!running)
        {
            break;
        }

        if (i == frames_wanted-1)
        {
            current_frame = (end_frame==video_frame_count)?end_frame-1:end_frame+1;
        }

        save_one_frame(current_frame, frame_number);

        i++;
        current_frame = start_frame + (i * frame_step);
        frame_number++;
    }

    if (running)
    {
        emit process_done();
    }
}

void FramesExtractor::save_one_frame(double current_frame,
                                     int frame_number)
{
    cv::Mat frame;
    cap->set(cv::CAP_PROP_POS_FRAMES, current_frame);
    *cap >> frame;

    int i = 1;
    while (frame.empty())
    {
        if (i == max_frames_to_backtrack)
        {
            qCritical() << tr("Unable to read a frame: %1 %2 %3")
                           .arg(current_frame)
                           .arg(frame_number)
                           .arg(video_frame_count);
            return;
        }
        i++;

        current_frame--;
        cap->set(cv::CAP_PROP_POS_FRAMES, current_frame);
        *cap >> frame;
    }

    double current_frame_secs = current_frame / video_fps;
    QTime a(0,0,0);
    a = a.addSecs(current_frame_secs);
    QString time = a.toString();

    QString file_path = out_dir_path;
    file_path += QString::number(frame_number);
    file_path += QString("[") + time + "].jpg";

    std::vector<int> params;
    params.push_back(cv::IMWRITE_JPEG_QUALITY);
    params.push_back(100);

    imwrite(file_path.toStdString(), frame, params);
}

bool FramesExtractor::set_video(QString file_path)
{
    cv::VideoCapture cap0(file_path.toStdString());
    if (!cap0.isOpened() || cap0.get(cv::CAP_PROP_FRAME_COUNT) <= 1)
    {
        return true;
    }
    delete cap;
    cap = new cv::VideoCapture(file_path.toStdString());
    return false;
}

int FramesExtractor::get_video_frame_count()
{
    return cap->get(cv::CAP_PROP_FRAME_COUNT);
}

double FramesExtractor::get_video_fps()
{
    return cap->get(cv::CAP_PROP_FPS);
}