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";
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
* 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
*
*
* @param cap VideoCapture object
* @param speed tape reading speed
* @return Frame
*/
Frame get_next_frame(VideoCapture& cap, float speed, bool skip = false) {
if (skip) {
int ms_to_skip = speed == 15 ? 79 : 157;
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) {
// Draw matches
Mat img_matches;
cv::drawMatches(templateShape, keypoints_object, halved_gray_current_frame, keypoints_scene, good_matches,
img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
// Localize the object
vector<Point2f> obj;
vector<Point2f> scene;
......@@ -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)
* @brief Compares two consecutive video frames and establish if there
* 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) {
* @return true if a potential Irregularity has been found;
* @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) {
bool result = false;
......@@ -656,31 +657,14 @@ void processing(cv::VideoCapture videoCapture, SceneObject capstan, SceneObject
int video_current_ms = videoCapture.get(CAP_PROP_POS_MSEC);
// counters
int savedFrames = 0;
float lastSaved = -160;
/* 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]
bool irregularity_found = false;
// The first frame of the video won't be processed
cv::Mat prevFrame;
videoCapture >> prevFrame;
cv::Mat prevFrame = get_next_frame(videoCapture, args.speed, irregularity_found);
firstInstant = video_length_ms - video_current_ms;
while (videoCapture.isOpened()) {
Frame currentFrame = get_next_frame(videoCapture, args.speed);
video_current_ms = videoCapture.get(CAP_PROP_POS_MSEC);
Frame frame;
videoCapture >> frame;
Frame frame = get_next_frame(videoCapture, args.speed, irregularity_found);
video_current_ms = videoCapture.get(CAP_PROP_POS_MSEC);
if (frame.empty()) {
......@@ -704,24 +688,20 @@ void processing(cv::VideoCapture videoCapture, SceneObject capstan, SceneObject
cout << "\rIrregularities: " << savedFrames << ". ";
cout << "Remaining video time [mm:ss]: " << minStrToEnd << ":" << secStrToEnd << flush;
if ((video_current_ms - lastSaved > savingRate) &&
frameDifference(prevFrame, frame, msToEnd, capstan, tape, args)) {
// An Irregularity has been found!
irregularity_found = is_frame_different(prevFrame, frame, msToEnd, capstan, tape, args);
if (irregularity_found) {
auto [odd_frame, even_frame] = frame.deinterlace();
string timeLabel = getTimeLabel(video_current_ms, ":");
string safeTimeLabel = getTimeLabel(video_current_ms, "-");
string irregularityImageFilename = to_string(savedFrames) + "_" + safeTimeLabel + ".jpg";
string irregularityImageFilename =
to_string(savedFrames) + "_" + getTimeLabel(video_current_ms, "-") + ".jpg";
cv::imwrite(irregularityImagesPath / irregularityImageFilename, odd_frame);
// 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();
irregularityFileOutput2["Irregularities"] +=
irreg.set_image_URI(irregularityImagesPath.string() + "/" + irregularityImageFilename).to_JSON();
lastSaved = video_current_ms;
savedFrames++;
}
......@@ -754,7 +734,6 @@ int main(int argc, char** argv) {
SceneObject tape = SceneObject::from_file(CONFIG_FILE, Object::TAPE);
json irregularityFileInput;
cv::Mat myFrame;
const fs::path VIDEO_PATH = args.workingPath / "PreservationAudioVisualFile" / args.filesName;
......@@ -811,12 +790,11 @@ int main(int argc, char** argv) {
int frames_number = videoCapture.get(CAP_PROP_FRAME_COUNT);
// Set frame position to half video length
videoCapture.set(CAP_PROP_POS_FRAMES, frames_number / 2);
// Get frame
videoCapture >> myFrame;
cv::Mat middle_frame = get_next_frame(videoCapture, args.speed);
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
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