<p>An efficient compute-shaded image filter would be emitted with (screenX / [kernel width], screenY / [kernel height], 1) groups and one kernel in each group, allowing texels to pass into groupshared memory and reducing the total number of samples at each pixel. But it seems like this will only apply the filter within the patches defined by each thread-group and create aliasing between them. Why doesn't this happen? If it does happen, how is it mitigated?</p>

CC BY-SA 4.0
2019-02-18T04:09:54.683Z
It's been a long while I've done any image processing but f I understand correctly you are talking about the convolution operation applied to images with a kernel matrix? In that case the kernel is applied on every pixel. Your local workgroup size is (kernel width, kernel height,1). If you apply the operation to every pixel in this group, then it'd equal to just looping every pixel in the entire image and applying the kernel. Why would there be aliasing?
gallickgunner
CC BY-SA 4.0
2019-02-18T04:17:19.713Z
I'm thinking because no information is shared between groups, so pixels at the edges of a group will catch much more influence from pixels on one side than from pixels on the other. Shouldn't that bias the image somehow? Aliasing maybe isn't the right word
Paul Ferris
CC BY-SA 4.0
2019-02-18T04:28:43.867Z
Ah if you are thinking it like that sure. I had a different picture in mind. You don't necessarily need to share information. If you pass the image as image2D you could just calculate the indices for the pixels required by the edge pixel in a group. Although half of those will lie in the other groups, you can still read from the image at those pixels assuming you are not reading and writing from the same image. You can't anyway i think there should be 2 images, one for reading and other for the filtered one.
gallickgunner
CC BY-SA 4.0
2019-02-18T05:58:02.400Z
Mm, either two images or some careful memory barriers with separated texel collection/convolution blocks :). Admitting texels outside the kernel works, but it also means sampling a few more texels...I wonder if it's possible to modify convolution so the edges are naturally accounted for without any extra samples.
Paul Ferris
CC BY-SA 4.0
2019-02-18T11:46:45.167Z
@PaulFerris Convolution becomes multiplication in the Fourier domain.
lightxbulb
CC BY-SA 4.0
2019-02-18T19:03:55.490Z
@lightxbulb which means aliasing doesn't occur because the multiplications can be applied discretely?
Paul Ferris
CC BY-SA 4.0
2019-02-18T19:10:41.710Z
@PaulFerris I have an issue with your definition of aliasing (it means something entirely different in image processing than what you have in mind). As far as the fourier domain goes, it will let you convolve your image efficiently with large filters by simply multiplying two fourier transformed images. There's a tradeoff obviously of going to the fourier domain and back. This can be done through FFT though which is $O(n\log n)$. So it really depends on your kernel size whether it's better/more efficient.
lightxbulb
CC BY-SA 4.0
2019-02-18T19:35:46.883Z
That's interesting, thanks. I'm using small kernels (up to 5x5), do you think the Fourier domain would be efficient at that scale?
Paul Ferris
CC BY-SA 4.0
2019-02-18T20:00:35.557Z
@PaulFerris Not really, 5x5 is small enough for you to do it directly, just use a texture for input and a texture for output. The other thing that you can look into (for more specialized cases) is summed area tables/integral images, which let you perform arbitrary region box filtering in constant time. There's generalizations to other filters foo, but it does require preprocessing of the image (can be done in parallel though).
lightxbulb
CC BY-SA 4.0
2019-02-18T23:29:51.667Z
mmm...I feel like preprocessing will wipe out any savings from using the tables (this is for a game engine, so there could be a different image every frame).
Paul Ferris
CC BY-SA 4.0
2019-02-18T23:46:31.653Z
I'll definitely consider them if blurring edge texels in like gallickgunnner suggested is too expensive, though ^_^. Would it be reasonable to interpolate between kernel regions after applying the filter? Given e.g. two patches you'd weight each separately, then compute the overall filter density for each and interpolate pixels towards one or the other depending on their position in the image.
Paul Ferris
CC BY-SA 4.0
2019-02-19T10:05:14.860Z
@PaulFerris I don't think it would make sense for what you want to do. Just do it normally, I don't think you can get rid of the fact that for each pixel you have to sample a different subset of the image. Just implement it and profile.
lightxbulb
CC BY-SA 4.0
2019-02-19T20:05:09.060Z
Right, will do; I'm almost definitely over-optimizing anyway. Thanks for the help :)
Paul Ferris
<image-processing><filtering><gpgpu>
Why don't discretization errors occur with compute-shaded kernel filters?
Paul Ferris
# Why don't discretization errors occur with compute-shaded kernel filters?

(Asked by: username_0 on 2019-02-17)

An efficient compute-shaded image filter would be emitted with (screenX / [kernel width], screenY / [kernel height], 1) groups and one kernel in each group, allowing texels to pass into groupshared memory and reducing the total number of samples at each pixel. But it seems like this will only apply the filter within the patches defined by each thread-group and create aliasing between them. Why doesn't this happen? If it does happen, how is it mitigated?

**Tags:** image-processing, filtering, gpgpu

> **Comments:**
> **username_1**: It's been a long while I've done any image processing but f I understand correctly you are talking about the convolution operation applied to images with a kernel matrix? In that case the kernel is applied on every pixel. Your local workgroup size is (kernel width, kernel height,1). If you apply the operation to every pixel in this group, then it'd equal to just looping every pixel in the entire image and applying the kernel. Why would there be aliasing?  
> **username_0**: I'm thinking because no information is shared between groups, so pixels at the edges of a group will catch much more influence from pixels on one side than from pixels on the other. Shouldn't that bias the image somehow? Aliasing maybe isn't the right word  
> **username_1**: Ah if you are thinking it like that sure. I had a different picture in mind. You don't necessarily need to share information. If you pass the image as image2D you could just calculate the indices for the pixels required by the edge pixel in a group. Although half of those will lie in the other groups, you can still read from the image at those pixels assuming you are not reading and writing from the same image. You can't anyway i think there should be 2 images, one for reading and other for the filtered one.  
> **username_0**: Mm, either two images or some careful memory barriers with separated texel collection/convolution blocks :). Admitting texels outside the kernel works, but it also means sampling a few more texels...I wonder if it's possible to modify convolution so the edges are naturally accounted for without any extra samples.  
> **username_2**: @username_0 Convolution becomes multiplication in the Fourier domain.  
> **username_0**: @username_2 which means aliasing doesn't occur because the multiplications can be applied discretely?  
> **username_2**: @username_0 I have an issue with your definition of aliasing (it means something entirely different in image processing than what you have in mind). As far as the fourier domain goes, it will let you convolve your image efficiently with large filters by simply multiplying two fourier transformed images. There's a tradeoff obviously of going to the fourier domain and back. This can be done through FFT though which is $O(n\log n)$. So it really depends on your kernel size whether it's better/more efficient.  
> **username_0**: That's interesting, thanks. I'm using small kernels (up to 5x5), do you think the Fourier domain would be efficient at that scale?  
> **username_2**: @username_0 Not really, 5x5 is small enough for you to do it directly, just use a texture for input and a texture for output. The other thing that you can look into (for more specialized cases) is summed area tables/integral images, which let you perform arbitrary region box filtering in constant time. There's generalizations to other filters foo, but it does require preprocessing of the image (can be done in parallel though).  
> **username_0**: mmm...I feel like preprocessing will wipe out any savings from using the tables (this is for a game engine, so there could be a different image every frame).  
> **username_0**: I'll definitely consider them if blurring edge texels in like gallickgunnner suggested is too expensive, though ^_^. Would it be reasonable to interpolate between kernel regions after applying the filter? Given e.g. two patches you'd weight each separately, then compute the overall filter density for each and interpolate pixels towards one or the other depending on their position in the image.  
> **username_2**: @username_0 I don't think it would make sense for what you want to do. Just do it normally, I don't think you can get rid of the fact that for each pixel you have to sample a different subset of the image. Just implement it and profile.  
> **username_0**: Right, will do; I'm almost definitely over-optimizing anyway. Thanks for the help :)  

---

## 0 answers

