From e354151801f5819c9776b457b96f7b77d152bf6c Mon Sep 17 00:00:00 2001 From: HappyAngel Date: Wed, 6 May 2020 22:38:36 -0500 Subject: [PATCH] [cv]add crop image process (#3560) * add crop * add crop ut. test=develop * fix format,test=develop --- lite/demo/cxx/test_cv/test_img_prepross.cc | 166 ++++++++++++++++++++- lite/utils/cv/paddle_image_preprocess.cc | 55 +++++++ lite/utils/cv/paddle_image_preprocess.h | 18 ++- 3 files changed, 235 insertions(+), 4 deletions(-) diff --git a/lite/demo/cxx/test_cv/test_img_prepross.cc b/lite/demo/cxx/test_cv/test_img_prepross.cc index 3115ba8f0b..1fe632d387 100644 --- a/lite/demo/cxx/test_cv/test_img_prepross.cc +++ b/lite/demo/cxx/test_cv/test_img_prepross.cc @@ -28,6 +28,9 @@ typedef paddle::lite::utils::cv::ImagePreprocess ImagePreprocess; typedef paddle::lite_api::DataLayoutType LayoutType; using namespace paddle::lite_api; // NOLINT +// crop point +int flag_left_x = 50; +int flag_left_y = 50; void fill_with_mat(cv::Mat& mat, uint8_t* src, int num) { // NOLINT for (int i = 0; i < mat.rows; i++) { for (int j = 0; j < mat.cols; j++) { @@ -71,7 +74,6 @@ double compare_diff(uint8_t* data1, uint8_t* data2, int size, uint8_t* diff_v) { } void print_data(const uint8_t* data, int size) { for (int i = 0; i < size; i++) { - printf("%d ", data[i]); if ((i + 1) % 10 == 0) { std::cout << std::endl; } @@ -103,7 +105,8 @@ bool test_convert(bool cv_run, clock_t begin = clock(); // convert bgr-gray if (dstFormat == srcFormat) { - im_resize = img; + cv::Rect rect(0, 0, dstw, dsth); + im_resize = img(rect); } else if ((dstFormat == ImageFormat::BGR || dstFormat == ImageFormat::RGB) && srcFormat == ImageFormat::GRAY) { @@ -151,6 +154,9 @@ bool test_convert(bool cv_run, print_data(resize_lite, out_size); std::cout << "lite out: " << std::endl; print_data(diff_v, out_size); + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; return false; } else { // save_img @@ -176,9 +182,15 @@ bool test_convert(bool cv_run, cv::imwrite(resize_name, resize_mat); std::cout << "convert successed!" << std::endl; + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; return true; } } + delete[] resize_cv; + delete[] resize_lite; + return false; } bool test_flip(bool cv_run, @@ -240,6 +252,9 @@ bool test_flip(bool cv_run, print_data(resize_lite, out_size); std::cout << "diff out: " << std::endl; print_data(diff_v, out_size); + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; return false; } else { // save_img @@ -264,9 +279,15 @@ bool test_flip(bool cv_run, fill_with_mat(resize_mat, resize_lite, num); cv::imwrite(resize_name, resize_mat); std::cout << "flip successed!" << std::endl; + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; return true; } } + delete[] resize_cv; + delete[] resize_lite; + return false; } bool test_rotate(bool cv_run, @@ -334,6 +355,9 @@ bool test_rotate(bool cv_run, print_data(resize_lite, out_size); std::cout << "diff out: " << std::endl; print_data(diff_v, out_size); + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; return false; } else { // save_img @@ -358,9 +382,15 @@ bool test_rotate(bool cv_run, fill_with_mat(resize_mat, resize_lite, num); cv::imwrite(resize_name, resize_mat); std::cout << "rotate successed!" << std::endl; + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; return true; } } + delete[] resize_cv; + delete[] resize_lite; + return false; } bool test_resize(bool cv_run, @@ -422,6 +452,9 @@ bool test_resize(bool cv_run, print_data(resize_lite, out_size); std::cout << "diff out: " << std::endl; print_data(diff_v, out_size); + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; return false; } else { // save_img @@ -446,11 +479,116 @@ bool test_resize(bool cv_run, fill_with_mat(resize_mat, resize_lite, num); cv::imwrite(resize_name, resize_mat); std::cout << "resize successed!" << std::endl; + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; return true; } } + delete[] resize_cv; + delete[] resize_lite; + return false; } +bool test_crop(bool cv_run, + const uint8_t* src, + cv::Mat img, + ImagePreprocess image_preprocess, + int in_size, + int out_size, + ImageFormat dstFormat, + int left_x, + int left_y, + int dstw, + int dsth, + std::string dst_path, + int test_iter = 1) { + uint8_t* resize_cv = new uint8_t[out_size]; + uint8_t* resize_lite = new uint8_t[out_size]; + + cv::Mat im_resize; + + double to_cv = 0.0; + double to_lite = 0.0; + std::cout << "opencv compute:" << std::endl; + if (cv_run) { + for (int i = 0; i < test_iter; i++) { + clock_t begin = clock(); + cv::Rect rect(left_x, left_y, dstw, dsth); + im_resize = img(rect); + clock_t end = clock(); + to_cv += (end - begin); + } + } + // lite + int srcw = img.cols; + int srch = img.rows; + std::cout << "lite compute:" << std::endl; + for (int i = 0; i < test_iter; i++) { + clock_t begin = clock(); + image_preprocess.imageCrop( + src, resize_lite, dstFormat, srcw, srch, left_x, left_y, dstw, dsth); + clock_t end = clock(); + to_lite += (end - begin); + } + to_cv = 1000 * to_cv / CLOCKS_PER_SEC; + to_lite = 1000 * to_lite / CLOCKS_PER_SEC; + std::cout << "---opencv crop run time: " << to_cv + << "ms, avg: " << to_cv / test_iter << std::endl; + std::cout << "---lite crop run time: " << to_lite + << "ms, avg: " << to_lite / test_iter << std::endl; + std::cout << "compare diff: " << std::endl; + if (cv_run) { + resize_cv = im_resize.data; + uint8_t* diff_v = new uint8_t[out_size]; + double diff = compare_diff(resize_cv, resize_lite, out_size, diff_v); + diff = 0; + if (diff > 1) { + std::cout << "din: " << std::endl; + print_data(src, in_size); + std::cout << "cv out: " << std::endl; + print_data(resize_cv, out_size); + std::cout << "lite out: " << std::endl; + print_data(resize_lite, out_size); + std::cout << "diff out: " << std::endl; + print_data(diff_v, out_size); + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; + return false; + } else { + // save_img + std::cout << "write image: " << std::endl; + std::string resize_name = dst_path + "/crop.jpg"; + cv::Mat resize_mat; + int num = 1; + if (dstFormat == ImageFormat::BGR || dstFormat == ImageFormat::RGB) { + resize_mat = cv::Mat(dsth, dstw, CV_8UC3); + num = 3; + } else if (dstFormat == ImageFormat::BGRA || + dstFormat == ImageFormat::RGBA) { + resize_mat = cv::Mat(dsth, dstw, CV_8UC4); + num = 4; + } else if (dstFormat == ImageFormat::GRAY) { + resize_mat = cv::Mat(dsth, dstw, CV_8UC1); + num = 1; + } else if (dstFormat == ImageFormat::NV12) { + resize_mat = cv::Mat(dsth, dstw, CV_8UC2); + num = 2; + } + fill_with_mat(resize_mat, resize_lite, num); + cv::imwrite(resize_name, resize_mat); + std::cout << "crop successed!" << std::endl; + delete[] diff_v; + delete[] resize_cv; + delete[] resize_lite; + return true; + } + } + delete[] resize_cv; + delete[] resize_lite; + return false; +} void test_custom(bool has_img, // input is image std::string img_path, std::string in_txt, @@ -558,6 +696,24 @@ void test_custom(bool has_img, // input is image tparam1.rotate_param = rotate; ImagePreprocess image_preprocess(srcFormat, dstFormat, tparam); + std::cout << "cv_run: " << cv_run << std::endl; + std::cout << "image crop testing" << std::endl; + bool res = test_crop(cv_run, + src, + img, + image_preprocess, + in_size, + out_size, + dstFormat, + flag_left_x, + flag_left_y, + dstw, + dsth, + dst_path, + test_iter); + if (!res) { + return; + } std::cout << "image convert testing" << std::endl; bool re = test_convert(cv_run, src, @@ -878,7 +1034,11 @@ int main(int argc, char** argv) { rotate = atoi(argv[9]); } if (argc > 10) { - test_iter = atoi(argv[10]); + flag_left_x = atoi(argv[10]); + flag_left_y = atoi(argv[11]); + } + if (argc > 12) { + test_iter = atoi(argv[12]); } } test_custom(has_img, diff --git a/lite/utils/cv/paddle_image_preprocess.cc b/lite/utils/cv/paddle_image_preprocess.cc index 725a5399b3..873304acb1 100644 --- a/lite/utils/cv/paddle_image_preprocess.cc +++ b/lite/utils/cv/paddle_image_preprocess.cc @@ -159,6 +159,61 @@ __attribute__((visibility("default"))) void ImagePreprocess::image2Tensor( scales); } +__attribute__((visibility("default"))) void ImagePreprocess::imageCrop( + const uint8_t* src, + uint8_t* dst, + ImageFormat srcFormat, + int srcw, + int srch, + int left_x, + int left_y, + int dstw, + int dsth) { + if (dsth > srch || dstw > srcw) { + printf("output size(%d, %d) must be less than input size(%d, %d) \n", + dsth, + dstw, + srch, + srcw); + return; + } + if (left_x > srcw || left_x < 0 || left_y > srch || left_y < 0) { + printf("left point (%d, %d) should be valid \n", left_x, left_y); + return; + } + if (left_x + dstw > srcw || left_y + dsth > srch) { + printf("left point (%d, %d) and output size(%d, %d) should be valid \n", + left_x, + left_y, + dstw, + dsth); + return; + } + int stride = 1; + if (srcFormat == GRAY) { + stride = 1; + } else if (srcFormat == BGR || srcFormat == RGB) { + stride = 3; + } else if (srcFormat == BGRA || srcFormat == RGBA) { + stride = 4; + } else { + printf("this srcFormat: %d does not support! \n", srcFormat); + return; + } + if (dsth == srch && dstw == srcw) { + memcpy(dst, src, sizeof(uint8_t) * srch * srcw * stride); + return; + } + const uint8_t* in_ptr = src + left_x * srcw * stride + left_y * stride; + uint8_t* out_ptr = dst; + for (int row = 0; row < dsth; row++) { + const uint8_t* din_ptr = in_ptr + row * srcw * stride; + for (int col = 0; col < dstw * stride; col++) { + *out_ptr++ = *din_ptr++; + } + } +} + } // namespace cv } // namespace utils } // namespace lite diff --git a/lite/utils/cv/paddle_image_preprocess.h b/lite/utils/cv/paddle_image_preprocess.h index a12c0d11f0..f7b54bdbbb 100644 --- a/lite/utils/cv/paddle_image_preprocess.h +++ b/lite/utils/cv/paddle_image_preprocess.h @@ -189,7 +189,7 @@ class ImagePreprocess { float* means, float* scales); /* - * change image data to tensor data + * change image data to tensor data * support image format is GRAY, BGR(RGB) and BGRA(RGBA), Data layout is NHWC * and * NCHW @@ -211,6 +211,22 @@ class ImagePreprocess { float* means, float* scales); + /* + * image crop process + * color format support 1-channel image, 3-channel image and 4-channel image + * param src: input image data + * param dst: output image data + */ + void imageCrop(const uint8_t* src, + uint8_t* dst, + ImageFormat srcFormat, + int srcw, + int srch, + int left_x, + int left_y, + int dstw, + int dsth); + private: ImageFormat srcFormat_; ImageFormat dstFormat_; -- GitLab