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:
- is considered bad-practice use high order scharr derivatives? why did opencv choose assert
dx+dy == 1
? 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.
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!
i've never read original
scharr
paper (the dissertation in german) don't know answer whyscharr()
function doesn't allow higher order derivatives. maybe because of first point make in #3 below?the
scharr
function supposed derivative. , total derivative of multivariable functionf(x) = f(x0, ..., xn)
isdf/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 useaddweighted()
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.
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 ofsobel
,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
Post a Comment