-
Notifications
You must be signed in to change notification settings - Fork 85
added cropping of capture/background #153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 22 commits
127009b
65627e8
7b41672
cb0fe4f
3eeb58b
01e9a75
f81e26e
112e979
22472ad
7dc9bcc
6894b3e
1769f7e
e9a5242
0f62a57
81c1c83
4c5f72c
ffb9883
7353ff8
5a92b93
5ee0d4a
44dbb6a
4c6431e
975b96f
481cb47
f80a8a6
ea1e350
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,8 @@ | |
| #include <opencv2/imgproc.hpp> | ||
| #include <opencv2/highgui.hpp> | ||
|
|
||
| #include <lib/libbackscrub.h> | ||
|
|
||
| // Internal state of background processing | ||
| struct background_t { | ||
| int debug; | ||
|
|
@@ -18,6 +20,7 @@ struct background_t { | |
| int frame; | ||
| double fps; | ||
| cv::Mat raw; | ||
| int bg_stored; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, I have modified this. Initializing was done with false, setting with true. |
||
| std::mutex rawmux; | ||
| cv::Mat thumb; | ||
| std::mutex thumbmux; | ||
|
|
@@ -130,6 +133,7 @@ std::shared_ptr<background_t> load_background(const std::string& path, int debug | |
| pbkd->debug = debug; | ||
| pbkd->video = false; | ||
| pbkd->run = false; | ||
| pbkd->bg_stored = false; | ||
| pbkd->cap.open(path, cv::CAP_ANY); // explicitly ask for auto-detection of backend | ||
| if (!pbkd->cap.isOpened()) { | ||
| if (pbkd->debug) fprintf(stderr, "background: cap cannot open: %s\n", path.c_str()); | ||
|
|
@@ -143,7 +147,7 @@ std::shared_ptr<background_t> load_background(const std::string& path, int debug | |
| // if: can read 2 video frames => it's a video | ||
| // else: is loaded as an image => it's an image | ||
| // else: it's not usable. | ||
| if (pbkd->cap.read(pbkd->raw) && pbkd->cap.read(pbkd->raw)) { | ||
| if (cnt > -1) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I recall, I chose this current method as
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will perform the tests. Using fps which shall be greater than 0.00000 for a video may be better.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately, my system don't work with animated.gif. Due to this I can't check if the fps which would be processed on systems allowing this will return a frame rate of 45 Fps (value obtained while converting the file via ffmpeg to a stream. Jpg file may contain a thumbnail image, do reading twice work, and the file is recognized as video. Reading 3 times will give the expected result, but this shall not be the right way. The test for picture/video is now based on the fps. I think that this shall always work.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll grab your PR and check what I find here in the next day or so - thanks.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I've checked the behaviour as the current PR has it (
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am surprised! For total_landscaping.jpg I get as output: What tell your system? I use Fedora 36 XFCE with opencv 4.5.5. What do you use? I have tried the following on my development environment: This is basically the same as the old condition, but I assume that the width of 2 consecutive images has to be the same. The detection was okay on my system.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to opencv cap.get(cv::CAP_PROP_FRAME_COUNT) return the 'Number of frames in the video file' Work with images as if they were a video is not a great idea. If the image has a big size, reading, ... will take more time as
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @phlash If I recall, I chose this current method as cnt could be > 1 for some image files (multiple resolutions?) but they would not play as a video... please test with all the variations in backgrounds folder smile
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jjsarton I'm running on Debian stable (11), OpenCV 4.5.1, here's what I get for each background type:
..so this looks like we are heavily dependant on unstable OpenCV behaviour 😞, and the reason I chose to ignore both fps and cnt, instead attempting to load two frames in sequence. |
||
| // it's a video, try a reset and start reader thread.. | ||
| if (pbkd->cap.set(cv::CAP_PROP_POS_FRAMES, 0)) | ||
| pbkd->frame = 0; | ||
|
|
@@ -183,13 +187,22 @@ int grab_background(std::shared_ptr<background_t> pbkd, int width, int height, c | |
| if (pbkd->video) { | ||
| // grab frame & frame no. under mutex | ||
| std::unique_lock<std::mutex> hold(pbkd->rawmux); | ||
| cv::resize(pbkd->raw, out, cv::Size(width, height)); | ||
| cv::Rect crop = bs_calc_cropping(pbkd->raw.cols, pbkd->raw.rows, width, height); | ||
| cv::resize(pbkd->raw(crop), out, cv::Size(width, height)); | ||
| frm = pbkd->frame; | ||
| } else { | ||
| // resize still image as requested into out | ||
| cv::resize(pbkd->raw, out, cv::Size(width, height)); | ||
| frm = 1; | ||
| } | ||
| if (!pbkd->bg_stored) { | ||
| // resize still image as requested into out | ||
| cv::Rect crop = bs_calc_cropping(pbkd->raw.cols, pbkd->raw.rows, width, height); | ||
| // Under some circumstances we must do the job in two steps! | ||
| // Otherwise this resize(pbkd->raw(crop), pbkd->raw, ...) may fail. | ||
| pbkd->raw(crop).copyTo(pbkd->raw); | ||
| cv::resize(pbkd->raw, pbkd->raw, cv::Size(width, height)); | ||
| pbkd->bg_stored = true; | ||
| } | ||
| out = pbkd->raw ; | ||
| frm = 1; | ||
| } | ||
|
phlash marked this conversation as resolved.
Outdated
|
||
| return frm; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -365,7 +365,11 @@ bool bs_maskgen_process(void *context, cv::Mat &frame, cv::Mat &mask) { | |
|
|
||
| // scale up into full-sized mask | ||
| cv::Mat tmpbuf; | ||
| cv::resize(ctx.ofinal(ctx.in_roidim),tmpbuf,ctx.mroi.size()); | ||
| // with body-pix-float-050-8.tflite the size of ctx.ofinal is 33x33 | ||
| // and the wanted roi may be greater as 33x33 so we can crash with | ||
| // cv::resize(ctx.ofinal(ctx.in_roidim),tmpbuf,ctx.mroi.size()); | ||
| ctx.ofinal.copyTo(tmpbuf); | ||
| cv::resize(tmpbuf, tmpbuf, ctx.mroi.size()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure this is correct? Selecting an ROI from the final output is done because we may have centred the frame into the model earlier (line 289), this change removes the selection step. The calculations at line 237 onward should ensure that After going away and thinking about this - this is a separate bug that you do not need to fix in this PR. Let's raise another issue for this.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I modified the original code because I had a crash within opencv.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have just tested this again. With the old code, using backscrub/models/body-pix-float-050-8.tflite I get again a crash, with my correction this work well.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep - it's because they have an output stride variable in the model which defaults to 32, so we get input dim/32 == 257/32 ~= 33. I'm happy to leave the crash for now, you are officially "not making it worse" with this PR 😁, and we'll probably want to revisit the logic in multiple places to fix this properly.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is now covered by issue #156, and thus can be fixed by a separate PR that properly deals with the fact that we do not account for models that have different input and output sizes at all. |
||
|
|
||
| // blur at full size for maximum smoothness | ||
| cv::blur(tmpbuf,ctx.mroi,ctx.blur); | ||
|
|
@@ -375,3 +379,24 @@ bool bs_maskgen_process(void *context, cv::Mat &frame, cv::Mat &mask) { | |
| return true; | ||
| } | ||
|
|
||
| cv::Rect bs_calc_cropping(int inWidth, int inHeight, int targetWidth, int targetHigh) { | ||
| // if the input and output aspect ratio are not the same | ||
| // we can crop the source image. For example if the | ||
| // input image has a 16:9 (1280x720) ratio and the output is 4:3 (960x720) | ||
| // we will return the cropRegion set as x=160, width=960, y=0, height=720 | ||
| // which is the centered part of the original image | ||
| cv::Rect cropRegion = {0, 0, 0, 0}; | ||
| float sc = (float)targetWidth / inWidth; | ||
| float st = (float)targetHigh / inHeight; | ||
| sc = st > sc ? st : sc; | ||
|
|
||
| int sx = (int)(targetWidth / sc) - inWidth; | ||
| cropRegion.x = (sx < 0 ? -sx : sx) / 2; | ||
|
|
||
| int sy = (int)(targetHigh / sc) - inHeight; | ||
| cropRegion.y = (sy < 0 ? -sy : sy) / 2; | ||
|
|
||
| cropRegion.width = inWidth - cropRegion.x * 2; | ||
| cropRegion.height = inHeight - cropRegion.y * 2; | ||
| return cropRegion; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.