Conversation
| static Ptr<ResizeNearestNeighborLayer> create(const LayerParams& params); | ||
| }; | ||
|
|
||
| class CV_EXPORTS ResizeBilinearLayer : public Layer |
There was a problem hiding this comment.
@dmonterom, what do you think about renaming ResizeNearestNeighborLayer to ResizeLayer and use interpolation strategy as an additional flag? Please add a test similar to nearest neighbor layer
opencv/modules/dnn/test/test_tf_importer.cpp
Lines 325 to 328 in 5b868cc
Using script from opencv/opencv_extra:
https://github.com/opencv/opencv_extra/blob/b467369489529d8eb2e847c13b117ec4e253a638/testdata/dnn/tensorflow/generate_tf_models.py#L258-L262
There was a problem hiding this comment.
Hi @dkurt, thats a good idea, I will change it as soon as possible. I will also add the new test soon.
There was a problem hiding this comment.
@dmonterom, thank you! It also can help us to resolve an issue #10985 with Interp layer from some of Caffe's forks smoother.
There was a problem hiding this comment.
Hey @dkurt, I made the changes (I also tested the two layers and everything seems ok). If you agree with them i will replace the resize nearest neighbor test with a new one.
There was a problem hiding this comment.
@dmonterom please add *_net, *_in and *_out files generated by script as a PR to opencv_extra with modified version of the script.
|
|
||
| layerParams.set("height", outSize.at<int>(0, 0)); | ||
| layerParams.set("width", outSize.at<int>(0, 1)); | ||
| layerParams.set("interpolation", 0); |
There was a problem hiding this comment.
Enumerations INTER_NEAREST and INTER_LINEAR are also integers. You can just set them as arguments, layerParams.set("interpolation", INTER_NEAREST); and use interpolation like resize(getPlane(inp, n, ch), getPlane(out, n, ch), Size(outWidth, outHeight), 0, 0, interpolation);
|
|
||
| connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); | ||
| } | ||
| else if (type == "ResizeBilinear") |
There was a problem hiding this comment.
Body of that case is absolutely the same. Can you just extend the previous one by else if (type == "ResizeNearestNeighbor" || type == "ResizeBilinear") and vary "interpolation" flag?
modules/dnn/src/init.cpp
Outdated
| CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer); | ||
| CV_DNN_REGISTER_LAYER_CLASS(Flatten, FlattenLayer); | ||
| CV_DNN_REGISTER_LAYER_CLASS(ResizeNearestNeighbor, ResizeNearestNeighborLayer); | ||
| CV_DNN_REGISTER_LAYER_CLASS(Resize, ResizeLayer); |
There was a problem hiding this comment.
Please align ResizeLayer with the other layers names.
| layerParams.set("height", outSize.at<int>(0, 0)); | ||
| layerParams.set("width", outSize.at<int>(0, 1)); | ||
| if (type == "ResizeNearestNeighbor") | ||
| layerParams.set("interpolation", 0); |
There was a problem hiding this comment.
I think INTER_NEAREST or INTER_LINEAR should be here.
There was a problem hiding this comment.
Hi, do you mean replacing the values by them? Then I should define them at the beginning or include imgproc.hpp, right?
There was a problem hiding this comment.
Why? They are just defined in OpenCV: https://docs.opencv.org/master/da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121 . And please do not forget to add a test.
|
Hi @dkurt, I have created a test for resize bilinear using the generator script, but when i run the test it fails: I have also regenerate the resize nearest one but it successes, so its not about my tensorflow version. |
|
@dmonterom, that is why we need to test it. Perhaps the problem is in borders.Try to figure out what values are different. Test on small inputs like |
|
@dkurt, I have been doing several tests with different sizes and they always fail. I found this information: |
|
@dmonterom, it'd nice if you can attach the results of your experiments. We need to know if difference is only at boundaries or in corners or in a whole image. Thanks! |
|
@dkurt, here is an example of blitznet with tensorflow and with OpenCV |
|
Thank you but I meant numerical experiments with resize of 5x5 inputs. We need to compare numbers first. |
|
@dmonterom, thank you for your work and research! It seems that TensorFlow's resize_bilinear is a quite different from OpenCV's INTER_LINEAR. Let me introduce you an experimental mechanic of custom layers. All that you need is just use changes from PR #11129 (work in progress for now). You may find a tutorial there. |
c1510ed to
d796353
Compare
|
@dmonterom, We slightly modified your PR to merge it. May I ask you to try it with your model again? |
| float input_y = y * heightScale; | ||
| int y0 = static_cast<int>(input_y); | ||
| const float* inpData_row0 = (float*)inp.data + y0 * inpWidth; | ||
| const float* inpData_row1 = (y0 + 1 < inpHeight) ? (inpData_row0 + inpWidth) : inpData_row0; |
There was a problem hiding this comment.
Use .ptr<float>(y0)
and .ptr<float>(std::min(y0 + 1, inpHeight - 1))
| int x0 = static_cast<int>(input_x); | ||
| int x1 = std::min(x0 + 1, inpWidth - 1); | ||
|
|
||
| float* outData = (float*)out.data + y * outWidth + x; |
| *outData = inpData_row0_c[x0] + | ||
| (input_y - y0) * (inpData_row1_c[x0] - inpData_row0_c[x0]) + | ||
| (input_x - x0) * (inpData_row0_c[x1] - inpData_row0_c[x0] + | ||
| (input_y - y0) * (inpData_row1_c[x1] - inpData_row0_c[x1] - inpData_row1_c[x0] + inpData_row0_c[x0])); |
There was a problem hiding this comment.
Why OpenCV cv::resize() with BORDER_REPLICATE doesn't work here? (answer: 0.5 pixel center)
Anyway, if you want to reuse OpenCV's INTER_LINEAR constant then it should have the same behavior as defined by this constant.
There was a problem hiding this comment.
@alalek, There are different topics that TenorFlow's resize_bilinear doesn't equal to OpenCV's one.
Replaced constants to string values.
There was a problem hiding this comment.
@alalek, if we extend cv::resize in the master branch and add the optional floating-point shift, will that make cv::resize suitable for implementation of this layer?
alternatively, can we use cv::warpAffine with the transformation matrix [fx, 0, shift_x; 0, fy, shift_y] to emulate the proper resize + shift?
There was a problem hiding this comment.
Two different formulas are usually used for resize operation:
x * widthScale- Something like
(x + 0.5) * widthScale - 0.5
The second formula is used in OpenVX, OpenCV's INTER_LINEAR resize (and probably generic INTER_AREA).
The first is used in OpenCV INTER_NEAREST (not accurate, but it is fast) / INTER_AREA (fast path).
Here, we need to use the first formula with "linear" interpolation (to match original framework operation).
There was a problem hiding this comment.
@alalek, it means that cv::warpAffine can do that?
Combined ResizeNearestNeighbor and ResizeBilinear layers into Resize (with an interpolation param). Minor changes to tf_importer and resize layer to save some code lines Minor changes in init.cpp Minor changes in tf_importer.cpp
59ee2aa to
5a7ca1b
Compare



This pullrequest changes
Added ResizeBilinear op for tensorflow importer.