Commit ee66ff7d authored by Matteo's avatar Matteo
Browse files

update

parent c862755d
# Software implementation
The core of the acquisition process is splitted in two AI-modules: the audio analyser and the video analyser. The video analyser takes advantage of computer vision to detect anomalies on the tape area recorded in video.
In simple words the analyser takes in input the video, takes a frame in the middle of the video to find ROIs
\ No newline at end of file
...@@ -181,24 +181,25 @@ static const string CAPSTAN_TEMPLATE_IMG = "input/capstanBERIO058prova.png"; ...@@ -181,24 +181,25 @@ static const string CAPSTAN_TEMPLATE_IMG = "input/capstanBERIO058prova.png";
static const string CONFIG_FILE = "config/config.json"; static const string CONFIG_FILE = "config/config.json";
/** /**
* @brief Get the next frame object * @brief Get the next frame object.
* *
* Whenever we find an Irregularity, we want to skip a lenght equal to the * Whenever we find an Irregularity, we want to skip a lenght equal to the
* Studer reading head (3 cm = 1.18 inches). * Studer reading head (3 cm = 1.18 inches).
*
* Note the following considerations: * Note the following considerations:
* - since we are analysing video at 25 fps a frame occurs every 40 ms * - since we are analysing video at 25 fps a frame occurs every 40 ms
* - at 15 ips we cross 3 cm of tape in 79 ms (2 frames) * - at 15 ips we cross 3 cm of tape in 79 ms (2 frames)
* - at 7.5 ips we cross 3 cm of tape in 157 ms (4 frames) * - at 7.5 ips we cross 3 cm of tape in 157 ms (4 frames)
*
* The considered lengths are the widths of the tape areas. * The considered lengths are the widths of the tape areas.
* The following condition constitutes a valid approach if the tape areas * The following condition constitutes a valid approach if the tape areas
* have widths always equal to the reading head * have widths always equal to the reading head
* *
* @param cap VideoCapture object * @param cap VideoCapture object
* @param speed tape reading speed * @param speed tape reading speed
* @return Frame * @return Frame
*/ */
Frame get_next_frame(VideoCapture& cap, float speed, bool skip = false) { Frame get_next_frame(VideoCapture& cap, float speed, bool skip = false) {
if (skip) { if (skip) {
int ms_to_skip = speed == 15 ? 79 : 157; int ms_to_skip = speed == 15 ? 79 : 157;
cap.set(CAP_PROP_POS_MSEC, cap.get(CAP_PROP_POS_MSEC) + ms_to_skip); cap.set(CAP_PROP_POS_MSEC, cap.get(CAP_PROP_POS_MSEC) + ms_to_skip);
...@@ -385,8 +386,8 @@ bool findProcessingAreas(Mat myFrame, SceneObject tape, SceneObject capstan) { ...@@ -385,8 +386,8 @@ bool findProcessingAreas(Mat myFrame, SceneObject tape, SceneObject capstan) {
// Draw matches // Draw matches
Mat img_matches; Mat img_matches;
cv::drawMatches(templateShape, keypoints_object, halved_gray_current_frame, keypoints_scene, good_matches, cv::drawMatches(templateShape, keypoints_object, halved_gray_current_frame, keypoints_scene, good_matches,
img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
// Localize the object // Localize the object
vector<Point2f> obj; vector<Point2f> obj;
vector<Point2f> scene; vector<Point2f> scene;
...@@ -508,7 +509,7 @@ Frame get_difference_for_roi(Frame previous, Frame current, RotatedRect roi) { ...@@ -508,7 +509,7 @@ Frame get_difference_for_roi(Frame previous, Frame current, RotatedRect roi) {
} }
/** /**
* @fn bool frameDifference(cv::Mat prevFrame, cv::Mat currentFrame, int * @fn bool is_frame_different(cv::Mat prevFrame, cv::Mat currentFrame, int
* msToEnd) * msToEnd)
* @brief Compares two consecutive video frames and establish if there * @brief Compares two consecutive video frames and establish if there
* potentially is an Irregularity. The comparison is pixel-wise and based on * potentially is an Irregularity. The comparison is pixel-wise and based on
...@@ -521,7 +522,7 @@ Frame get_difference_for_roi(Frame previous, Frame current, RotatedRect roi) { ...@@ -521,7 +522,7 @@ Frame get_difference_for_roi(Frame previous, Frame current, RotatedRect roi) {
* @return true if a potential Irregularity has been found; * @return true if a potential Irregularity has been found;
* @return false otherwise. * @return false otherwise.
*/ */
bool frameDifference(cv::Mat prevFrame, cv::Mat currentFrame, int msToEnd, SceneObject capstan, SceneObject tape, bool is_frame_different(cv::Mat prevFrame, cv::Mat currentFrame, int msToEnd, SceneObject capstan, SceneObject tape,
Args args) { Args args) {
bool result = false; bool result = false;
...@@ -656,31 +657,14 @@ void processing(cv::VideoCapture videoCapture, SceneObject capstan, SceneObject ...@@ -656,31 +657,14 @@ void processing(cv::VideoCapture videoCapture, SceneObject capstan, SceneObject
int video_current_ms = videoCapture.get(CAP_PROP_POS_MSEC); int video_current_ms = videoCapture.get(CAP_PROP_POS_MSEC);
// counters // counters
int savedFrames = 0; int savedFrames = 0;
float lastSaved = -160; bool irregularity_found = false;
/* Whenever we find an Irregularity, we want to skip a lenght equal to the
* Studer reading head (3 cm = 1.18 inches).
* Note the following considerations:
* - since we are analysing video at 25 fps a frame occurs every 40 ms
* - at 15 ips we cross 3 cm of tape in 79 ms (2 frames)
* - at 7.5 ips we cross 3 cm of tape in 157 ms (4 frames)
* The considered lengths are the widths of the tape areas.
* The following condition constitutes a valid approach if the tape areas
* have widths always equal to the reading head
*/
int savingRate = args.speed == 7.5 ? 157 : 79; // [ms]
// The first frame of the video won't be processed // The first frame of the video won't be processed
cv::Mat prevFrame; cv::Mat prevFrame = get_next_frame(videoCapture, args.speed, irregularity_found);
videoCapture >> prevFrame;
firstInstant = video_length_ms - video_current_ms; firstInstant = video_length_ms - video_current_ms;
while (videoCapture.isOpened()) { while (videoCapture.isOpened()) {
Frame frame = get_next_frame(videoCapture, args.speed, irregularity_found);
Frame currentFrame = get_next_frame(videoCapture, args.speed);
video_current_ms = videoCapture.get(CAP_PROP_POS_MSEC);
Frame frame;
videoCapture >> frame;
video_current_ms = videoCapture.get(CAP_PROP_POS_MSEC); video_current_ms = videoCapture.get(CAP_PROP_POS_MSEC);
if (frame.empty()) { if (frame.empty()) {
...@@ -704,24 +688,20 @@ void processing(cv::VideoCapture videoCapture, SceneObject capstan, SceneObject ...@@ -704,24 +688,20 @@ void processing(cv::VideoCapture videoCapture, SceneObject capstan, SceneObject
cout << "\rIrregularities: " << savedFrames << ". "; cout << "\rIrregularities: " << savedFrames << ". ";
cout << "Remaining video time [mm:ss]: " << minStrToEnd << ":" << secStrToEnd << flush; cout << "Remaining video time [mm:ss]: " << minStrToEnd << ":" << secStrToEnd << flush;
if ((video_current_ms - lastSaved > savingRate) && irregularity_found = is_frame_different(prevFrame, frame, msToEnd, capstan, tape, args);
frameDifference(prevFrame, frame, msToEnd, capstan, tape, args)) { if (irregularity_found) {
// An Irregularity has been found!
auto [odd_frame, even_frame] = frame.deinterlace(); auto [odd_frame, even_frame] = frame.deinterlace();
string timeLabel = getTimeLabel(video_current_ms, ":"); string irregularityImageFilename =
string safeTimeLabel = getTimeLabel(video_current_ms, "-"); to_string(savedFrames) + "_" + getTimeLabel(video_current_ms, "-") + ".jpg";
string irregularityImageFilename = to_string(savedFrames) + "_" + safeTimeLabel + ".jpg";
cv::imwrite(irregularityImagesPath / irregularityImageFilename, odd_frame); cv::imwrite(irregularityImagesPath / irregularityImageFilename, odd_frame);
// Append Irregularity information to JSON // Append Irregularity information to JSON
Irregularity irreg = Irregularity(Source::Video, timeLabel); Irregularity irreg = Irregularity(Source::Video, getTimeLabel(video_current_ms, ":"));
irregularityFileOutput1["Irregularities"] += irreg.to_JSON(); irregularityFileOutput1["Irregularities"] += irreg.to_JSON();
irregularityFileOutput2["Irregularities"] += irregularityFileOutput2["Irregularities"] +=
irreg.set_image_URI(irregularityImagesPath.string() + "/" + irregularityImageFilename).to_JSON(); irreg.set_image_URI(irregularityImagesPath.string() + "/" + irregularityImageFilename).to_JSON();
lastSaved = video_current_ms;
savedFrames++; savedFrames++;
} }
...@@ -754,7 +734,6 @@ int main(int argc, char** argv) { ...@@ -754,7 +734,6 @@ int main(int argc, char** argv) {
SceneObject tape = SceneObject::from_file(CONFIG_FILE, Object::TAPE); SceneObject tape = SceneObject::from_file(CONFIG_FILE, Object::TAPE);
json irregularityFileInput; json irregularityFileInput;
cv::Mat myFrame;
const fs::path VIDEO_PATH = args.workingPath / "PreservationAudioVisualFile" / args.filesName; const fs::path VIDEO_PATH = args.workingPath / "PreservationAudioVisualFile" / args.filesName;
...@@ -811,12 +790,11 @@ int main(int argc, char** argv) { ...@@ -811,12 +790,11 @@ int main(int argc, char** argv) {
int frames_number = videoCapture.get(CAP_PROP_FRAME_COUNT); int frames_number = videoCapture.get(CAP_PROP_FRAME_COUNT);
// Set frame position to half video length // Set frame position to half video length
videoCapture.set(CAP_PROP_POS_FRAMES, frames_number / 2); videoCapture.set(CAP_PROP_POS_FRAMES, frames_number / 2);
// Get frame cv::Mat middle_frame = get_next_frame(videoCapture, args.speed);
videoCapture >> myFrame;
cout << "Video resolution: " << myFrame.cols << "x" << myFrame.rows << endl; cout << "Video resolution: " << middle_frame.cols << "x" << middle_frame.rows << endl;
bool found = findProcessingAreas(myFrame, tape, capstan); bool found = findProcessingAreas(middle_frame, tape, capstan);
// Reset frame position // Reset frame position
videoCapture.set(CAP_PROP_POS_FRAMES, 0); videoCapture.set(CAP_PROP_POS_FRAMES, 0);
......
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