c++ - combined Scharr derivatives in opencv -


i have few questions regarding scharr derivatives , opencv implementation.

i interested in second order image derivatives (3x3) kernels. started sobel second derivative, failed find thin lines in images. after reading sobel , charr comparison in bottom of this page, decided try scharr instead changing line:

sobel(gray, grad, ddepth, 2, 2, 3, scale, delta, border_default);

to line:

scharr(img, gray, ddepth, 2, 2, scale, delta, border_default );

my problem seems cv::scharr allows performing first order of 1 partial derivative @ time, following error:

error: (-215) dx >= 0 && dy >= 0 && dx+dy == 1 in function getscharrkernels

(see assertion line here)

following restriction, have few questions regarding scharr derivatives:

  1. is considered bad-practice use high order scharr derivatives? why did opencv choose assert dx+dy == 1?
  2. if call scharr twice each axis, correct way combine results? using:

    addweighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );

    but not sure how sobel function combines 2 axis , in order should done 4 derivatives.

  3. if compute (dx=2,dy=2) derivative using 4 different kernels, reduce processing time unifying 4 kernels 1 before applying on image (i assume cv::sobel does). there reasonable way create such combined shcarr kernel , convolve image?

thanks!

  1. i've never read original scharr paper (the dissertation in german) don't know answer why scharr() function doesn't allow higher order derivatives. maybe because of first point make in #3 below?

  2. the scharr function supposed derivative. , total derivative of multivariable function f(x) = f(x0, ..., xn) is

    df/dx = dx0*df/dx0 + ... + dxn*df/dxn 

    that is, sum of partials each multiplied change. in case of images of course, change dx in input single pixel, it's equivalent 1. in other words, sum partials; not weighting them half. can use addweighted() 1s weights, or can sum them, make sure won't saturate image you'll need convert float or 16-bit image first. however, it's pretty common compute euclidean magnitude of derivatives, too, if you're trying gradient instead of derivative.

    however, that's first-order derivative. higher orders, need apply chain ruling. see here details of combining second order.

  3. note optimized kernel first-order derivatives not optimal kernel second-order derivatives applying twice. scharr himself has paper on optimizing second-order derivative kernels, can read here.

    with said, filters split x , y directions make linear separable filters, turn 2d convolution problem 2 1d convolutions smaller kernels. think of sobel , scharr kernels: x direction, both have single column on either side same values (except 1 negative). when slide kernel across image, @ first location, you're multiplying first column , third column values in kernel. , 2 steps later, you're multiplying third , fifth. third computed, that's wasteful. instead, since both sides same, multiply each column vector since know need values, , can values results in column 1 , 3 , subtract them.

    in short, don't think can combine them built-in separable filter functions, because values positive sometimes, , negative otherwise; , way know when applying filter linearly them separately. however, can examine result of applying both filters , see how affect single pixel, construct 2d kernel, , convolve opencv.

suppose have 3x3 image:

image ===== b c  d e f  g h 

and have scharr kernels:

kernel_x ======== -3    0   3 -10   0   10 -3    0   3  kernel_y ======== -3   -10  -3  0    0    0  3    10   3 

the result of applying each kernel image gives us:

image * kernel_x ================ -3a  -10b  -3c  +0d  +0e   +0f +3g  +10h  +3i    image * kernel_y   ================ -3a   +0b  +3c  -10d  +0e  +10f  -3g   +0h  +3i 

these values summed , placed pixel e. since sum of both of these total derivative, sum all these values pixel e @ end of day.

image * kernel_x + image * kernel y =================================== -3a -10b -3c           +3g +10h +3i -3a      +3c -10d +10f -3g      +3i +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -6a -10b +0c -10d +10f +0g +10h +6i 

and same result we'd have gotten if multiplied kernel

kernel_xy ============= -6   -10   0 -10   0    10  0    10   6 

so there's 2d kernel single-order derivative. notice interesting? it's addition of 2 kernels. surprising? not really, x(a+b) = ax + bx. can pass filter2d() compute addition of derivatives. give same result?

import cv2 import numpy np  img = cv2.imread('cameraman.png', 0).astype(np.float32)  kernel = np.array([[-6, -10, 0],                    [-10, 0, 10],                    [0, 10, 6]])  total_first_derivative = cv2.filter2d(img, -1, kernel)  scharr_x = cv2.scharr(img, -1, 1, 0) scharr_y = cv2.scharr(img, -1, 0, 1)  print((total_first_derivative == (scharr_x + scharr_y)).all()) 

true

yep. guess can twice.


Comments

Popular posts from this blog

resizing Telegram inline keyboard -

command line - How can a Python program background itself? -

php - "cURL error 28: Resolving timed out" on Wordpress on Azure App Service on Linux -