fix canny when size is 7

This commit is contained in:
Xiao Tianci 2021-03-15 14:29:43 +08:00
parent 0451a800bc
commit b88a68c9e8
3 changed files with 69 additions and 15 deletions

View File

@ -32,7 +32,7 @@
namespace mindspore {
namespace dataset {
static void GetSobelKernel(float *kernel, int flag, int ksize) {
static void GetSobelKernel(float *kernel, int flag, int ksize, double scale) {
std::vector<float> buffer(ksize + 1);
float *ptr = kernel;
@ -70,12 +70,14 @@ static void GetSobelKernel(float *kernel, int flag, int ksize) {
}
}
scale = flag == 0 ? scale : 1.0;
for (int i = 0; i < ksize; i++) {
ptr[i] = buffer[i];
ptr[i] = buffer[i] * scale;
}
}
bool Sobel(const LiteMat &src, LiteMat &dst, int flag_x, int flag_y, int ksize, PaddBorderType pad_type) { // NOLINT
bool Sobel(const LiteMat &src, LiteMat &dst, int flag_x, int flag_y, int ksize, double scale, // NOLINT
PaddBorderType pad_type) {
if (src.IsEmpty() || src.data_type_ != LDataType::UINT8) {
return false;
}
@ -92,8 +94,8 @@ bool Sobel(const LiteMat &src, LiteMat &dst, int flag_x, int flag_y, int ksize,
kx.Init(ksize, 1, 1, LDataType::FLOAT32);
ky.Init(1, ksize, 1, LDataType::FLOAT32);
GetSobelKernel(kx, flag_x, ksize);
GetSobelKernel(ky, flag_y, ksize);
GetSobelKernel(kx, flag_x, ksize, scale);
GetSobelKernel(ky, flag_y, ksize, scale);
return ConvRowCol(src, kx, ky, dst, LDataType::FLOAT32, pad_type);
}
@ -106,6 +108,24 @@ static float GetEdge(const std::vector<float> &temp, int width, int height, int
}
}
static float Round(float value) {
// rounding if the result is even
// eg. 1.5 -> 2, 2.5 -> 2
float rnd = round(value);
float rnd_l = floor(value);
float rnd_h = ceil(value);
if (value - rnd_l == 0.5) {
if (fmod(rnd, 2) == 0) {
return rnd;
} else if (value > 0) {
return rnd_l;
} else {
return rnd_h;
}
}
return rnd;
}
static void NonMaximumSuppression(const LiteMat &gx, const LiteMat &gy, LiteMat &edges, bool L2gradient) { // NOLINT
edges.Init(gx.width_, gx.height_, gx.channel_, gx.data_type_);
@ -116,8 +136,8 @@ static void NonMaximumSuppression(const LiteMat &gx, const LiteMat &gy, LiteMat
int size = gx.height_ * gx.width_;
std::vector<float> temp(size);
for (int i = 0; i < size; i++) {
float gx_value = gx_ptr[i];
float gy_value = gy_ptr[i];
float gx_value = Round(gx_ptr[i]);
float gy_value = Round(gy_ptr[i]);
if (L2gradient) {
temp[i] = sqrt(gx_value * gx_value + gy_value * gy_value);
} else {
@ -127,8 +147,8 @@ static void NonMaximumSuppression(const LiteMat &gx, const LiteMat &gy, LiteMat
for (int y = 0; y < gx.height_; y++) {
for (int x = 0; x < gx.width_; x++) {
float gx_value = gx_ptr[y * gx.width_ + x];
float gy_value = gy_ptr[y * gx.width_ + x];
float gx_value = Round(gx_ptr[y * gx.width_ + x]);
float gy_value = Round(gy_ptr[y * gx.width_ + x]);
float gx_value_abs = std::abs(gx_value);
float gy_value_abs = std::abs(gy_value);
@ -242,9 +262,13 @@ bool Canny(const LiteMat &src, LiteMat &dst, double low_thresh, double high_thre
dst.Init(src.width_, src.height_, src.channel_, src.data_type_);
}
double scale = ksize == 7 ? 1 / 16.0 : 1.0;
low_thresh *= scale;
high_thresh *= scale;
LiteMat gx, gy;
Sobel(src, gx, 1, 0, ksize, PaddBorderType::PADD_BORDER_REPLICATE);
Sobel(src, gy, 0, 1, ksize, PaddBorderType::PADD_BORDER_REPLICATE);
Sobel(src, gx, 1, 0, ksize, scale, PaddBorderType::PADD_BORDER_REPLICATE);
Sobel(src, gy, 0, 1, ksize, scale, PaddBorderType::PADD_BORDER_REPLICATE);
LiteMat edges;
NonMaximumSuppression(gx, gy, edges, L2gradient);

View File

@ -148,7 +148,8 @@ bool ConvRowCol(const LiteMat &src, const LiteMat &kx, const LiteMat &ky, LiteMa
PaddBorderType pad_type = PaddBorderType::PADD_BORDER_DEFAULT);
/// \brief Filter the image by a Sobel kernel
bool Sobel(const LiteMat &src, LiteMat &dst, int flag_x, int flag_y, int ksize, PaddBorderType pad_type);
bool Sobel(const LiteMat &src, LiteMat &dst, int flag_x, int flag_y, int ksize = 3, double scale = 1.0,
PaddBorderType pad_type = PaddBorderType::PADD_BORDER_DEFAULT);
/// \brief Convert RGB image or color image to grayscale image
bool ConvertRgbToGray(const LiteMat &src, LDataType data_type, int w, int h, LiteMat &mat);

View File

@ -1595,6 +1595,35 @@ TEST_F(MindDataImageProcess, TestCannySize5) {
EXPECT_EQ(distance, 0.0f);
}
TEST_F(MindDataImageProcess, TestCannySize7) {
std::string filename = "data/dataset/apple.jpg";
cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR);
cv::Mat gray_image;
cv::cvtColor(src_image, gray_image, CV_BGR2GRAY);
cv::Mat dst_image;
cv::Canny(gray_image, dst_image, 110, 220, 7);
cv::Mat rgba_mat;
cv::cvtColor(src_image, rgba_mat, CV_BGR2RGBA);
bool ret = false;
LiteMat lite_mat_gray;
ret =
InitFromPixel(rgba_mat.data, LPixelType::RGBA2GRAY, LDataType::UINT8, rgba_mat.cols, rgba_mat.rows, lite_mat_gray);
ASSERT_TRUE(ret == true);
LiteMat lite_mat_dst;
ret = Canny(lite_mat_gray, lite_mat_dst, 110, 220, 7);
ASSERT_TRUE(ret == true);
int total_size = lite_mat_dst.height_ * lite_mat_dst.width_ * lite_mat_dst.channel_;
double distance = 0.0f;
for (int i = 0; i < total_size; i++) {
distance += pow((uint8_t)dst_image.data[i] - ((uint8_t *)lite_mat_dst)[i], 2);
}
distance = sqrt(distance / total_size);
EXPECT_EQ(distance, 0.0f);
}
TEST_F(MindDataImageProcess, TestCannyL2) {
std::string filename = "data/dataset/apple.jpg";
cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR);
@ -1689,8 +1718,8 @@ TEST_F(MindDataImageProcess, TestSobel) {
ASSERT_TRUE(ret == true);
LiteMat lite_mat_x;
LiteMat lite_mat_y;
Sobel(lite_mat_gray, lite_mat_x, 1, 0, 3, PaddBorderType::PADD_BORDER_REPLICATE);
Sobel(lite_mat_gray, lite_mat_y, 0, 1, 3, PaddBorderType::PADD_BORDER_REPLICATE);
Sobel(lite_mat_gray, lite_mat_x, 1, 0, 3, 1, PaddBorderType::PADD_BORDER_REPLICATE);
Sobel(lite_mat_gray, lite_mat_y, 0, 1, 3, 1, PaddBorderType::PADD_BORDER_REPLICATE);
ASSERT_TRUE(ret == true);
cv::Mat dst_imageX(lite_mat_x.height_, lite_mat_x.width_, CV_32FC1, lite_mat_x.data_ptr_);
@ -1731,7 +1760,7 @@ TEST_F(MindDataImageProcess, TestSobelFlag) {
InitFromPixel(rgba_mat.data, LPixelType::RGBA2GRAY, LDataType::UINT8, rgba_mat.cols, rgba_mat.rows, lite_mat_gray);
ASSERT_TRUE(ret == true);
LiteMat lite_mat_x;
Sobel(lite_mat_gray, lite_mat_x, 3, 1, 5, PaddBorderType::PADD_BORDER_REPLICATE);
Sobel(lite_mat_gray, lite_mat_x, 3, 1, 5, 1, PaddBorderType::PADD_BORDER_REPLICATE);
ASSERT_TRUE(ret == true);
cv::Mat dst_imageX(lite_mat_x.height_, lite_mat_x.width_, CV_32FC1, lite_mat_x.data_ptr_);