mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge pull request #24539 from LaurentBerger:blobrecttoimage
Add blobrecttoimage #24539 ### Pull Request Readiness Checklist resolves https://github.com/opencv/opencv/issues/14659 See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work #14659 - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
parent
fa5ed62a66
commit
3e6dcdc0a4
@ -1222,6 +1222,20 @@ CV__DNN_INLINE_NS_BEGIN
|
|||||||
CV_PROP_RW DataLayout datalayout; //!< Order of output dimensions. Choose DNN_LAYOUT_NCHW or DNN_LAYOUT_NHWC.
|
CV_PROP_RW DataLayout datalayout; //!< Order of output dimensions. Choose DNN_LAYOUT_NCHW or DNN_LAYOUT_NHWC.
|
||||||
CV_PROP_RW ImagePaddingMode paddingmode; //!< Image padding mode. @see ImagePaddingMode.
|
CV_PROP_RW ImagePaddingMode paddingmode; //!< Image padding mode. @see ImagePaddingMode.
|
||||||
CV_PROP_RW Scalar borderValue; //!< Value used in padding mode for padding.
|
CV_PROP_RW Scalar borderValue; //!< Value used in padding mode for padding.
|
||||||
|
|
||||||
|
/** @brief Get rectangle coordinates in original image system from rectangle in blob coordinates.
|
||||||
|
* @param rBlob rect in blob coordinates.
|
||||||
|
* @param size original input image size.
|
||||||
|
* @returns rectangle in original image coordinates.
|
||||||
|
*/
|
||||||
|
CV_WRAP Rect blobRectToImageRect(const Rect &rBlob, const Size &size);
|
||||||
|
|
||||||
|
/** @brief Get rectangle coordinates in original image system from rectangle in blob coordinates.
|
||||||
|
* @param rBlob rect in blob coordinates.
|
||||||
|
* @param rImg result rect in image coordinates.
|
||||||
|
* @param size original input image size.
|
||||||
|
*/
|
||||||
|
CV_WRAP void blobRectsToImageRects(const std::vector<Rect> &rBlob, CV_OUT std::vector<Rect>& rImg, const Size& size);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Creates 4-dimensional blob from image with given params.
|
/** @brief Creates 4-dimensional blob from image with given params.
|
||||||
|
@ -127,6 +127,34 @@ class dnn_test(NewOpenCVTests):
|
|||||||
targets = cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_OPENCV)
|
targets = cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_OPENCV)
|
||||||
self.assertTrue(cv.dnn.DNN_TARGET_CPU in targets)
|
self.assertTrue(cv.dnn.DNN_TARGET_CPU in targets)
|
||||||
|
|
||||||
|
def test_blobRectsToImageRects(self):
|
||||||
|
paramNet = cv.dnn.Image2BlobParams()
|
||||||
|
paramNet.size = (226, 226)
|
||||||
|
paramNet.ddepth = cv.CV_32F
|
||||||
|
paramNet.mean = [0.485, 0.456, 0.406]
|
||||||
|
paramNet.scalefactor = [0.229, 0.224, 0.225]
|
||||||
|
paramNet.swapRB = False
|
||||||
|
paramNet.datalayout = cv.dnn.DNN_LAYOUT_NCHW
|
||||||
|
paramNet.paddingmode = cv.dnn.DNN_PMODE_LETTERBOX
|
||||||
|
rBlob = np.zeros(shape=(20, 4), dtype=np.int32)
|
||||||
|
rImg = paramNet.blobRectsToImageRects(rBlob, (356, 356))
|
||||||
|
self.assertTrue(type(rImg[0, 0])==np.int32)
|
||||||
|
self.assertTrue(rImg.shape==(20, 4))
|
||||||
|
|
||||||
|
def test_blobRectToImageRect(self):
|
||||||
|
paramNet = cv.dnn.Image2BlobParams()
|
||||||
|
paramNet.size = (226, 226)
|
||||||
|
paramNet.ddepth = cv.CV_32F
|
||||||
|
paramNet.mean = [0.485, 0.456, 0.406]
|
||||||
|
paramNet.scalefactor = [0.229, 0.224, 0.225]
|
||||||
|
paramNet.swapRB = False
|
||||||
|
paramNet.datalayout = cv.dnn.DNN_LAYOUT_NCHW
|
||||||
|
paramNet.paddingmode = cv.dnn.DNN_PMODE_LETTERBOX
|
||||||
|
rBlob = np.zeros(shape=(20, 4), dtype=np.int32)
|
||||||
|
rImg = paramNet.blobRectToImageRect((0, 0, 0, 0), (356, 356))
|
||||||
|
self.assertTrue(type(rImg[0])==int)
|
||||||
|
|
||||||
|
|
||||||
def test_blobFromImage(self):
|
def test_blobFromImage(self):
|
||||||
np.random.seed(324)
|
np.random.seed(324)
|
||||||
|
|
||||||
|
@ -382,6 +382,66 @@ void imagesFromBlob(const cv::Mat& blob_, OutputArrayOfArrays images_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect Image2BlobParams::blobRectToImageRect(const Rect &r, const Size &oriImage)
|
||||||
|
{
|
||||||
|
CV_Assert(!oriImage.empty());
|
||||||
|
std::vector<Rect> rImg, rBlob;
|
||||||
|
rBlob.push_back(Rect(r));
|
||||||
|
rImg.resize(1);
|
||||||
|
this->blobRectsToImageRects(rBlob, rImg, oriImage);
|
||||||
|
return Rect(rImg[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image2BlobParams::blobRectsToImageRects(const std::vector<Rect> &rBlob, std::vector<Rect>& rImg, const Size& imgSize)
|
||||||
|
{
|
||||||
|
Size size = this->size;
|
||||||
|
rImg.resize(rBlob.size());
|
||||||
|
if (size != imgSize)
|
||||||
|
{
|
||||||
|
if (this->paddingmode == DNN_PMODE_CROP_CENTER)
|
||||||
|
{
|
||||||
|
float resizeFactor = std::max(size.width / (float)imgSize.width,
|
||||||
|
size.height / (float)imgSize.height);
|
||||||
|
for (int i = 0; i < rBlob.size(); i++)
|
||||||
|
{
|
||||||
|
rImg[i] = Rect((rBlob[i].x + 0.5 * (imgSize.width * resizeFactor - size.width)) / resizeFactor,
|
||||||
|
(rBlob[i].y + 0.5 * (imgSize.height * resizeFactor - size.height)) / resizeFactor,
|
||||||
|
rBlob[i].width / resizeFactor,
|
||||||
|
rBlob[i].height / resizeFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->paddingmode == DNN_PMODE_LETTERBOX)
|
||||||
|
{
|
||||||
|
float resizeFactor = std::min(size.width / (float)imgSize.width,
|
||||||
|
size.height / (float)imgSize.height);
|
||||||
|
int rh = int(imgSize.height * resizeFactor);
|
||||||
|
int rw = int(imgSize.width * resizeFactor);
|
||||||
|
|
||||||
|
int top = (size.height - rh) / 2;
|
||||||
|
int left = (size.width - rw) / 2;
|
||||||
|
for (int i = 0; i < rBlob.size(); i++)
|
||||||
|
{
|
||||||
|
rImg[i] = Rect((rBlob[i].x - left) / resizeFactor,
|
||||||
|
(rBlob[i].y - top) / resizeFactor,
|
||||||
|
rBlob[i].width / resizeFactor,
|
||||||
|
rBlob[i].height / resizeFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->paddingmode == DNN_PMODE_NULL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rBlob.size(); i++)
|
||||||
|
{
|
||||||
|
rImg[i] = Rect(rBlob[i].x * (float)imgSize.width / size.width,
|
||||||
|
rBlob[i].y * (float)imgSize.height / size.height,
|
||||||
|
rBlob[i].width * (float)imgSize.width / size.width,
|
||||||
|
rBlob[i].height * (float)imgSize.height / size.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CV_Error(CV_StsBadArg, "Unknown padding mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CV__DNN_INLINE_NS_END
|
CV__DNN_INLINE_NS_END
|
||||||
}} // namespace cv::dnn
|
}} // namespace cv::dnn
|
||||||
|
@ -13,6 +13,72 @@
|
|||||||
|
|
||||||
namespace opencv_test { namespace {
|
namespace opencv_test { namespace {
|
||||||
|
|
||||||
|
TEST(blobRectToImageRect, DNN_PMODE_NULL)
|
||||||
|
{
|
||||||
|
Size inputSize(50 + (rand() % 100) / 4 * 4, 50 + (rand() % 100) / 4 * 4);
|
||||||
|
Size imgSize(200 + (rand() % 100) / 4 * 4, 200 + (rand() % 100) / 4 * 4);
|
||||||
|
Rect rBlob(inputSize.width / 2 - inputSize.width / 4, inputSize.height / 2 - inputSize.height / 4, inputSize.width / 2, inputSize.height / 2);
|
||||||
|
Image2BlobParams paramNet;
|
||||||
|
paramNet.scalefactor = Scalar::all(1.f);
|
||||||
|
paramNet.size = inputSize;
|
||||||
|
paramNet.ddepth = CV_32F;
|
||||||
|
paramNet.mean = Scalar();
|
||||||
|
paramNet.swapRB = false;
|
||||||
|
paramNet.datalayout = DNN_LAYOUT_NHWC;
|
||||||
|
paramNet.paddingmode = DNN_PMODE_NULL;
|
||||||
|
Rect rOri = paramNet.blobRectToImageRect(rBlob, imgSize);
|
||||||
|
Rect rImg = Rect(rBlob.x * (float)imgSize.width / inputSize.width, rBlob.y * (float)imgSize.height / inputSize.height,
|
||||||
|
rBlob.width * (float)imgSize.width / inputSize.width, rBlob.height * (float)imgSize.height / inputSize.height);
|
||||||
|
ASSERT_EQ(rImg, rOri);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(blobRectToImageRect, DNN_PMODE_CROP_CENTER)
|
||||||
|
{
|
||||||
|
Size inputSize(50 + (rand() % 100) / 4 * 4, 50 + (rand() % 100) / 4 * 4);
|
||||||
|
Size imgSize(200 + (rand() % 100) / 4 * 4, 200 + (rand() % 100) / 4 * 4);
|
||||||
|
Rect rBlob(inputSize.width / 2 - inputSize.width / 4, inputSize.height / 2 - inputSize.height / 4, inputSize.width / 2, inputSize.height / 2);
|
||||||
|
Image2BlobParams paramNet;
|
||||||
|
paramNet.scalefactor = Scalar::all(1.f);
|
||||||
|
paramNet.size = inputSize;
|
||||||
|
paramNet.ddepth = CV_32F;
|
||||||
|
paramNet.mean = Scalar();
|
||||||
|
paramNet.swapRB = false;
|
||||||
|
paramNet.datalayout = DNN_LAYOUT_NHWC;
|
||||||
|
paramNet.paddingmode = DNN_PMODE_CROP_CENTER;
|
||||||
|
Rect rOri = paramNet.blobRectToImageRect(rBlob, imgSize);
|
||||||
|
float resizeFactor = std::max(inputSize.width / (float)imgSize.width,
|
||||||
|
inputSize.height / (float)imgSize.height);
|
||||||
|
Rect rImg = Rect((rBlob.x + 0.5 * (imgSize.width * resizeFactor - inputSize.width)) / resizeFactor, (rBlob.y + 0.5 * (imgSize.height * resizeFactor - inputSize.height)) / resizeFactor,
|
||||||
|
rBlob.width / resizeFactor, rBlob.height / resizeFactor);
|
||||||
|
ASSERT_EQ(rImg, rOri);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(blobRectToImageRect, DNN_PMODE_LETTERBOX)
|
||||||
|
{
|
||||||
|
Size inputSize(50 + (rand() % 100) / 4 * 4, 50 + (rand() % 100) / 4 * 4);
|
||||||
|
Size imgSize(200 + (rand() % 100) / 4 * 4, 200 + (rand() % 100) / 4 * 4);
|
||||||
|
Rect rBlob(inputSize.width / 2 - inputSize.width / 4, inputSize.height / 2 - inputSize.height / 4, inputSize.width / 2, inputSize.height / 2);
|
||||||
|
Image2BlobParams paramNet;
|
||||||
|
paramNet.scalefactor = Scalar::all(1.f);
|
||||||
|
paramNet.size = inputSize;
|
||||||
|
paramNet.ddepth = CV_32F;
|
||||||
|
paramNet.mean = Scalar();
|
||||||
|
paramNet.swapRB = false;
|
||||||
|
paramNet.datalayout = DNN_LAYOUT_NHWC;
|
||||||
|
paramNet.paddingmode = DNN_PMODE_LETTERBOX;
|
||||||
|
Rect rOri = paramNet.blobRectToImageRect(rBlob, imgSize);
|
||||||
|
float resizeFactor = std::min(inputSize.width / (float)imgSize.width,
|
||||||
|
inputSize.height / (float)imgSize.height);
|
||||||
|
int rh = int(imgSize.height * resizeFactor);
|
||||||
|
int rw = int(imgSize.width * resizeFactor);
|
||||||
|
|
||||||
|
int top = (inputSize.height - rh) / 2;
|
||||||
|
int left = (inputSize.width - rw) / 2;
|
||||||
|
Rect rImg = Rect((rBlob.x - left) / resizeFactor, (rBlob.y - top) / resizeFactor, rBlob.width / resizeFactor, rBlob.height / resizeFactor);
|
||||||
|
ASSERT_EQ(rImg, rOri);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(blobFromImage_4ch, Regression)
|
TEST(blobFromImage_4ch, Regression)
|
||||||
{
|
{
|
||||||
Mat ch[4];
|
Mat ch[4];
|
||||||
|
Loading…
Reference in New Issue
Block a user