Commit 7944a0f3 authored by Matteo's avatar Matteo
Browse files

refactor frameDifference function

parent 6f21c5c1
......@@ -10,10 +10,10 @@
* Currently, this program is only compatible with the Studer A810 and videos recorded in PAL standard.
*
* @authors Nadir Dalla Pozza <nadir.dallapozza@unipd.it>, Matteo Spanio <dev2@audioinnova.com>
* @copyright 2022, Audio Innova S.r.l.
* @copyright 2023, Audio Innova S.r.l.
* @credits Niccolò Pretto, Nadir Dalla Pozza, Sergio Canazza
* @license GPL v3.0
* @version 1.1.0
* @version 1.1.1
* @status Production
*/
#include <filesystem>
......@@ -113,6 +113,16 @@ double rotatedRectArea(RotatedRect rect) {
return rect.size.width * rect.size.height;
}
/**
* @brief Prints a text in a given color.
*
* @param text
* @param color
*/
void pprint(string text, string color) {
cout << color << text << END << endl;
}
/**
* @brief Get operation arguments from command line or config.json file.
*
......@@ -328,24 +338,6 @@ bool findProcessingAreas(Mat myFrame) {
Vec4f positionTape( rect.center.x, rect.center.y + rect.size.height / 2 + 20 * (rect.size.width / 200), 1, rect.angle );
rectTape = utility::drawShapes(myFrame, positionTape, Scalar(0, 255-indexPos*64, 0), rect.size.width, 50 * (rect.size.width / 200), 0, 0, 1);
json autoJSON;
autoJSON["PreservationAudioVisualFile"] = fileName;
autoJSON["RotatedRect"] = {
{
"CenterX", rectTape.center.x
}, {
"CenterY", rectTape.center.y
}, {
"Width", rectTape.size.width
}, {
"Height", rectTape.size.height
}, {
"Angle", rectTape.angle
}
};
files::saveFile(fs::path("./" + fileName + ".json"), autoJSON.dump(4), false);
/*********************************************************************************************/
/************************************* CAPSTAN DETECTION *************************************/
/*********************************************************************************************/
......@@ -453,6 +445,38 @@ bool findProcessingAreas(Mat myFrame) {
return true;
}
RotatedRect check_skew(RotatedRect roi) {
// get angle and size from the bounding box
// thanks to http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
cv::Size rect_size = roi.size;
float angle = roi.angle;
if (roi.angle < -45.) {
angle += 90.0;
swap(rect_size.width, rect_size.height);
}
return RotatedRect(roi.center, rect_size, angle);
}
/**
* @brief Look for differences in two consecutive frames in a specific region of interest
*
* @param previous the reference frame
* @param current the frame to compare with the reference
* @param roi the region of interest
* @return Frame the difference matrix between the two frames
*/
Frame get_difference_for_roi(Frame previous, Frame current, RotatedRect roi) {
cv::Mat rotation_matrix = getRotationMatrix2D(roi.center, roi.angle, 1.0);
return previous
.warp(rotation_matrix)
.crop(roi.size, roi.center)
.difference(current
.warp(rotation_matrix)
.crop(roi.size, roi.center));
}
/**
* @brief Compares two consecutive video frames and establish if there potentially is an Irregularity.
......@@ -466,9 +490,7 @@ bool findProcessingAreas(Mat myFrame) {
*/
bool frameDifference(cv::Mat prevFrame, cv::Mat currentFrame, int msToEnd) {
/*********************************************************************************************/
/********************************** Capstan analysis *****************************************/
/*********************************************************************************************/
// In the last minute of the video, check for pinchRoller position for endTape event
if (!endTapeSaved && msToEnd < 60000) {
......@@ -477,37 +499,14 @@ bool frameDifference(cv::Mat prevFrame, cv::Mat currentFrame, int msToEnd) {
int capstanAreaPixels = rectCapstan.size.width * rectCapstan.size.height;
float capstanDifferentPixelsThreshold = capstanAreaPixels * capstan.threshold.percentual / 100;
// Extract matrices corresponding to the processing area
// CODE FROM https://answers.opencv.org/question/497/extract-a-rotatedrect-area/
// matrices we'll use
Mat M, rotatedPrevFrame, croppedPrevFrame, rotatedCurrentFrame, croppedCurrentFrame;
// get angle and size from the bounding box
float angle = rectCapstan.angle;
Size rect_size = rectCapstan.size;
// thanks to http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
if (rectCapstan.angle < -45.) {
angle += 90.0;
swap(rect_size.width, rect_size.height);
}
// get the rotation matrix
M = getRotationMatrix2D(rectCapstan.center, angle, 1.0);
// perform the affine transformation
cv::warpAffine(prevFrame, rotatedPrevFrame, M, prevFrame.size(), INTER_CUBIC);
cv::warpAffine(currentFrame, rotatedCurrentFrame, M, currentFrame.size(), INTER_CUBIC);
// crop the resulting image
cv::getRectSubPix(rotatedPrevFrame, rect_size, rectCapstan.center, croppedPrevFrame);
cv::getRectSubPix(rotatedCurrentFrame, rect_size, rectCapstan.center, croppedCurrentFrame);
// END CODE FROM https://answers.opencv.org/question/497/extract-a-rotatedrect-area/
cv::Mat differenceFrame = utility::difference(croppedPrevFrame, croppedCurrentFrame);
RotatedRect corrected_capstan_roi = check_skew(rectCapstan);
Frame difference_frame = get_difference_for_roi(Frame(prevFrame), Frame(currentFrame), corrected_capstan_roi);
int blackPixelsCapstan = 0;
for (int i = 0; i < croppedCurrentFrame.rows; i++) {
for (int j = 0; j < croppedCurrentFrame.cols; j++) {
if (differenceFrame.at<cv::Vec3b>(i, j)[0] == 0) {
for (int i = 0; i < difference_frame.rows; i++) {
for (int j = 0; j < difference_frame.cols; j++) {
if (difference_frame.at<cv::Vec3b>(i, j)[0] == 0) {
// There is a black pixel, then there is a difference between previous and current frames
blackPixelsCapstan++;
}
......@@ -518,53 +517,30 @@ bool frameDifference(cv::Mat prevFrame, cv::Mat currentFrame, int msToEnd) {
savingPinchRoller = true;
endTapeSaved = true; // Never check again for end tape instant
return true;
} else {
savingPinchRoller = false;
}
} else {
savingPinchRoller = false; // It will already be false before the last minute of the video. After having saved the capstan, the next time reset the variable to not save again
}
}
/*********************************************************************************************/
savingPinchRoller = false; // It will already be false before the last minute of the video. After having saved the capstan, the next time reset the variable to not save again
/************************************ Tape analysis ******************************************/
/*********************************************************************************************/
// Tape area
int tapeAreaPixels = rotatedRectArea(rectTape);
float tapeDifferentPixelsThreshold = tapeAreaPixels * tape.threshold.percentual / 100;
// Extract matrices corresponding to the processing area
// CODE FROM https://answers.opencv.org/question/497/extract-a-rotatedrect-area/
RotatedRect corrected_tape_roi = check_skew(rectTape);
// matrices we'll use
Mat M, rotatedPrevFrame, croppedPrevFrame, rotatedCurrentFrame, croppedCurrentFrame;
// get angle and size from the bounding box
float angle = rectTape.angle;
Size rect_size = rectTape.size;
// thanks to http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
if (rectTape.angle < -45.) {
angle += 90.0;
swap(rect_size.width, rect_size.height);
}
// get the rotation matrix
M = getRotationMatrix2D(rectTape.center, angle, 1.0);
// perform the affine transformation
cv::warpAffine(prevFrame, rotatedPrevFrame, M, prevFrame.size(), INTER_CUBIC);
cv::warpAffine(currentFrame, rotatedCurrentFrame, M, currentFrame.size(), INTER_CUBIC);
// crop the resulting image
cv::getRectSubPix(rotatedPrevFrame, rect_size, rectTape.center, croppedPrevFrame);
cv::getRectSubPix(rotatedCurrentFrame, rect_size, rectTape.center, croppedCurrentFrame);
Frame croppedCurrentFrame = Frame(currentFrame)
.warp(getRotationMatrix2D(corrected_tape_roi.center, corrected_tape_roi.angle, 1.0))
.crop(corrected_tape_roi.size, corrected_tape_roi.center);
// END CODE FROM https://answers.opencv.org/question/497/extract-a-rotatedrect-area/
cv::Mat differenceFrame = utility::difference(croppedPrevFrame, croppedCurrentFrame);
Frame difference_frame = get_difference_for_roi(Frame(prevFrame), Frame(currentFrame), corrected_tape_roi);
int decEnd = (msToEnd % 1000) / 100;
int secEnd = (msToEnd - (msToEnd % 1000)) / 1000;
int minEnd = secEnd / 60;
secEnd = secEnd % 60;
/************************************* Segment analysis **************************************/
int blackPixels = 0;
......@@ -574,7 +550,7 @@ bool frameDifference(cv::Mat prevFrame, cv::Mat currentFrame, int msToEnd) {
for (int i = 0; i < croppedCurrentFrame.rows; i++) {
for (int j = 0; j < croppedCurrentFrame.cols; j++) {
totColoreCF += croppedCurrentFrame.at<cv::Vec3b>(i, j)[0] + croppedCurrentFrame.at<cv::Vec3b>(i, j)[1] + croppedCurrentFrame.at<cv::Vec3b>(i, j)[2];
if (differenceFrame.at<cv::Vec3b>(i, j)[0] == 0) {
if (difference_frame.at<cv::Vec3b>(i, j)[0] == 0) {
blackPixels++;
}
}
......@@ -729,17 +705,11 @@ void processing(cv::VideoCapture videoCapture) {
} else {
unsavedFrames++;
}
prevFrame = frame;
}
}
/*************************************************************************************************/
/********************************************* MAIN **********************************************/
/*************************************************************************************************/
/**
* @brief main program, organised as:
* - Get input from command line or config.json file;
......@@ -859,7 +829,7 @@ int main(int argc, char** argv) {
videoCapture.set(CAP_PROP_POS_FRAMES, 0);
if (!found) {
cout << RED << "Processing area not found. Try changing JSON parameters." << END << endl;
pprint("Processing area not found. Try changing JSON parameters.", RED);
return -1; // Program terminated early
}
......@@ -867,7 +837,7 @@ int main(int argc, char** argv) {
/**************************************** PROCESSING *****************************************/
/*********************************************************************************************/
cout << '\n' << CYAN << "Starting processing..." << END << '\n';
pprint("\nProcessing...", CYAN);
// Processing timer
time_t startTimer, endTimer;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment