No announcement yet.

Filters 101

  • Filter
  • Time
  • Show
Clear All
new posts

  • #21

    Is that what you want to do?

    Click image for larger version  Name:	tree.png Views:	0 Size:	916.0 KB ID:	784421
    if the answer is yes, then, there is an easy way to achieve bluring without complex computation.

    Using image reduction, then resizing the resulting image to the same size than the original.

    Image 1, is the original
    Image 2, is using a 160 x 120 size reduction, then resized to 640 x 480
    Image 3, is using 80 x 60, then 640 x 480

    Note: This is what is being used by DWM to produce the Windows blur effect.

    See also the examples i posted there long ago (to emulate the VISTA blur effect on XP)
    Patrice Terrier
    Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).


    • #22
      Hi Patrice!

      Thanks for the response.

      I was interested in the general code for applying convolution filters. The blur filter just happened to be one I was using for testing my convolution code. I had in mind experimenting with multiple filters to see what kinds of results I could get.

      My interest in filters is related to a topic from another thread, regarding hi-speed conversion of incoming video to a binary color pair.

      The conversion works great on images, but with video there is a "shimmer" throughout the converted images.

      So I thought I would investigate filters to see if I can get a significant improvement in the quality of the image - a reduction in the shimmer that I'm seeing.

      Have you experienced the shimmer that I'm describing and do you have a suggestion on how to eliminate it during real-time conversions?
      Last edited by Gary Beene; 29 Aug 2019, 10:56 AM. Reason: ?Pierre? What was I thinking?


      • #23
        Originally posted by Gary Beene View Post
        Thanks for your comments/example. As best I can tell, my example in #10 matches the description you gave. It would seem that as Dan says, the blur for a single pass 3x3 filter is quite minimal.

        I tried out your code with strength=64 and iterations=20 and the blurring was minimal. Does that sound right? I'll go find the forum link for your code and see what values are appropriate to get a more pronounced blur.

        I'm not sure what you mean by this:

        Would you give some more details on what you're describing?

        I had not seen the w/h of the image calculated as you did, with this ...

         xl = @LPTR_ref[-2] - 1
        yl = @LPTR_ref[-1] - 1
        I've just followed Bob's example of using CVL.
        This program provides an example of magnifying and enhancing data.
        The filter is applied in two passes, one vertical and one horizontal.
        As you know, the bleedover of data is increased by reiteration.
        This allows the blur to be achieved through iteration once in each direction.
        It also includes a contrast enhancement filter.
        Clicking on the tiny desktop image in the lower left corner allows selection of a new area.
        #COMPILE EXE
        #DIM ALL
        #INCLUDE ""
        ENUM ctrls SINGULAR
            grfx = 500
        END ENUM
        TYPE bgra
            b AS BYTE
            g AS BYTE
            r AS BYTE
            a AS BYTE
        END TYPE
            LOCAL hWin, xitcode, hfont AS LONG
            FONT NEW "", 14 TO hfont
            DIALOG NEW PIXELS, 0, "Magnify Test", , , 732, 530, %WS_BORDER OR %WS_CAPTION OR %WS_SYSMENU TO hWin
            CONTROL ADD BUTTON, hWin, %bgimage, "Refresh Background",  3, 1, 240, 24
            CONTROL ADD LABEL, hWin, %lbl01, "Plain Magnified View", 246, 1, 240, 25, %SS_CENTER
            CONTROL ADD LABEL, hWin, %lbl02, "Enhanced Magnified View", 489, 1, 240, 25, %SS_CENTER
            CONTROL SET COLOR hWin, %lbl01, %GREEN, %BLACK
            CONTROL SET FONT hWin, %lbl01, hfont
            CONTROL SET COLOR hWin, %lbl02, %GREEN, %BLACK
            CONTROL SET FONT hWin, %lbl02, hfont
            CONTROL ADD GRAPHIC, hWin, %grfx, "", 3, 26, 240, 360
            GRAPHIC ATTACH hWin, %grfx
            CONTROL ADD GRAPHIC, hWin, %viewport, "", 3, 389, 240, 135, %SS_NOTIFY
            GRAPHIC ATTACH hWin, %viewport
            CONTROL ADD GRAPHIC, hWin, %grfxmag, "", 246, 26, 240, 500
            GRAPHIC ATTACH hWin, %grfxmag
            CONTROL ADD GRAPHIC, hWin, %grfxmagblur, "", 489, 26, 240, 500
            GRAPHIC ATTACH hWin, %grfxmagblur
            DIALOG SHOW MODAL hWin, CALL dlgproc() TO xitcode
            FONT END hfont
            FUNCTION = xitcode
        CALLBACK FUNCTION dlgproc()
            LOCAL getvalue AS STRING, xy AS POINT, hwnd AS DWORD
            SELECT CASE CB.MSG
                CASE %WM_INITDIALOG
                    DIALOG POST CB.HNDL, %WM_COMMAND, %bgimage, %BN_CLICKED
                CASE %WM_COMMAND
                    SELECT CASE CB.CTL
                        CASE %bgimage
                            IF CB.CTLMSG = %BN_CLICKED THEN
                                get_background CB.HNDL, %grfx, %viewport
                                GRAPHIC ATTACH CB.HNDL, %grfxmag, REDRAW
                                GRAPHIC STRETCH CB.HNDL, %grfx, (0, 0)-(59, 124) TO (0, 0)-(239,499), 0, %HALFTONE
                                GRAPHIC REDRAW
                                GRAPHIC GET BITS TO getvalue
                                GRAPHIC ATTACH CB.HNDL, %grfxmagblur, REDRAW
                                GRAPHIC STRETCH CB.HNDL, %grfx, (0, 0)-(59, 124) TO (0, 0)-(239, 499), 0, %HALFTONE
                                GRAPHIC GET BITS TO getvalue
                                getvalue = gnorm(getvalue)
                                GRAPHIC SET BITS getvalue
                                GRAPHIC REDRAW
                            END IF
                        CASE %viewport
                            IF CB.CTLMSG = %stn_clicked THEN
                                CONTROL HANDLE CB.HNDL, CB.CTL TO hwnd
                                screentoclient(hwnd, xy)
                                CONTROL SET USER CB.HNDL, CB.CTL, 1, xy.x
                                CONTROL SET USER CB.HNDL, CB.CTL, 2, xy.y
                            END IF
                            DIALOG POST CB.HNDL, %WM_COMMAND, %bgimage, %BN_CLICKED
                    END SELECT
            END SELECT
        SUB get_background(dlg AS DWORD, ctl AS LONG, v AS LONG)
            LOCAL DC_desktop, DC_ctl, hbmp AS DWORD, x, y, xx, yy, scx, scy, vx, vy AS LONG
            scx = METRICS(MAXIMIZED.X)
            scy = METRICS(MAXIMIZED.Y)
            CONTROL GET SIZE dlg, ctl TO x, y
            CONTROL GET USER dlg, v, 1 TO xx
            CONTROL GET USER dlg, v, 2 TO yy
            CONTROL GET SIZE dlg, v TO vx, vy
            xx = xx * scx \ vx
            yy = yy * scy \ vy
            DC_desktop = getdc(0)
            GRAPHIC ATTACH dlg, ctl, REDRAW
            GRAPHIC GET DC TO DC_ctl
            bitblt(DC_ctl, 0, 0, x, y, DC_desktop, xx, yy, %srccopy)
            GRAPHIC REDRAW
            GRAPHIC ATTACH dlg, v, REDRAW
            GRAPHIC GET DC TO DC_ctl
            stretchblt(DC_ctl, 0, 0, vx, vy, DC_desktop, 0, 0, scx, scy, %srccopy)
            GRAPHIC REDRAW
            releasedc(0, DC_desktop)
        END SUB
            LOCAL STR_nrm, STR_buf AS STRING, xL, yL, x, y, c, cxy, prcnt AS LONG
            LOCAL BPTR_nrm AS BYTE POINTER, LPTR_buf AS LONG POINTER, PXs(), PXd() AS bgra
            STR_buf = EnhanceContrast(STR_src, 70)
            STR_nrm = STR_src
            LPTR_buf = STRPTR(STR_buf)
            xL = @LPTR_buf
            yL = @LPTR_buf[1]
            REDIM PXs(xL - 1, yL - 1) AT STRPTR(STR_buf) + 8
            REDIM PXd(xL - 1, yL - 1) AT STRPTR(STR_nrm) + 8
            FOR x = 2 TO xL - 3
                FOR y = 0 TO yL - 1
                    PXd(x,y).b = (PXs(x-2,y).b+PXs(x-1,y).b*6+PXs(x,y).b*21+PXs(x+1,y).b*6+PXs(x+2,y).b)\35
                    PXd(x,y).g = (PXs(x-2,y).g+PXs(x-1,y).g*6+PXs(x,y).g*21+PXs(x+1,y).g*6+PXs(x+2,y).g)\35
                    PXd(x,y).r = (PXs(x-2,y).r+PXs(x-1,y).r*6+PXs(x,y).r*21+PXs(x+1,y).r*6+PXs(x+2,y).r)\35
            STR_buf = STR_nrm
            FOR y = 2 TO yL - 3
                FOR x = 0 TO xL - 1
                    PXd(x,y).b = (PXs(x,y-2).b+PXs(x,y-1).b*6+PXs(x,y).b*21+PXs(x,y+1).b*6+PXs(x,y+2).b)\35
                    PXd(x,y).g = (PXs(x,y-2).g+PXs(x,y-1).g*6+PXs(x,y).g*21+PXs(x,y+1).g*6+PXs(x,y+2).g)\35
                    PXd(x,y).r = (PXs(x,y-2).r+PXs(x,y-1).r*6+PXs(x,y).r*21+PXs(x,y+1).r*6+PXs(x,y+2).r)\35
            FUNCTION = STR_nrm
        FUNCTION EnhanceContrast(STR_src AS STRING, boost AS LONG) AS STRING
            LOCAL c, x, dv, median AS LONG, BPTR_buf AS BYTE POINTER, STR_buf AS STRING
            dv = 255 + boost
            median = boost \ 2
            STR_buf = STR_src
            BPTR_buf = STRPTR(STR_buf)
            FOR x = 8 TO LEN(STR_buf) - 1
                c = ((@BPTR_buf[x] * dv) \ 255) - median
                SELECT CASE c
                    CASE > 255 : @BPTR_buf[x] = 255
                    CASE < 0   : @BPTR_buf[x] =   0
                    CASE ELSE  : @BPTR_buf[x] =   c
                END SELECT
            FUNCTION = STR_buf
        The world is strange and wonderful.*
        I reserve the right to be horrifically wrong.
        Please maintain a safe following distance.
        *wonderful sold separately.


        • #24
          Originally posted by Gary Beene View Post

          I tested your filter and got this. Does this look correct?

          Click image for larger version

Name:	pb_2146.jpg
Views:	78
Size:	15.6 KB
ID:	784418

          I'm still not sure that my filter code is working correctly.
          That filter was a simple edge-detect, so I would have expected the horizon and shoreline to be very prominent, and the sky less so. Does your programme display the before & after images full-size or are they scaled down at all?


          • #25
            No scaling is used.


            • #26
              I tried to write a short programme to do this, but failed. I couldn't get GRAPHIC LOAD BITMAP to load your tree image. I did get a working demo using Qt/C++, which doesn't help you very much but it does reassure me that the filter I suggested does what I said.

              It's possible that the edge-detect filter is returning negative values: does your output image use the absolute values that come out of the filter?

              I'll look again at your code tomorrow.


              • #27
                Hi Dan!

                My code does not use absolute values. I hadn't read that to be a requirement. I'll give it a try!


                • #28

                  I've finally got your code to work. GRAPHIC BITMAP LOAD still refuses to play with your tree.bmp, so I had to write some code to load a bitmap file the old-fashioned way (and convert it from 32bpp to 24bpp for GRAPHIC SET BITS). And it turns out my old version on PB/Win doesn't support some of the language features you used. So, after all that, my mangling of your code has the image colours messed up (not sure why) and the image upside-down, but the actual convolution part does work for me.

                  The only bug I found was that you're hard-coding a divisor of 9. Replace this with the sum of the filter values (or with 1 when the sum is zero!), and I think you're good.

                  Many filters are capable of returning values greater than 255 or less than zero, so you do have to guard against that. A filter like this, for example:
                  -1 0 1
                  -2 0 2
                  -1 0 1
                  detects vertical edges, but gives either a positive or negative result depending whether the edge is bright-to-dark or dark-to-bright. (It's one of two filters comprising the Sobel edge-detector, and by doing maths on the outputs of both of them you can get a decent approximation of the angle of the detected line.)


                  • #29

                    I fixed the problems in my copy of your code, so I could compare properly with my Qt/C++ effort.

                    I addition to fixing the divisor, you also need to ensure that the result fits within an unsigned byte. Change your iCount variable to a DOUBLE, then after dividing by the divisor take its ABSolute value, and clip that to a max of 255 before copying it back to the RGBA component byte.