Seminko

Removing background from a picture

3 posts in this topic

#1 ·  Posted (edited)

Hey fellas,

alright, I have to confess, I'm in over my head :).

I'm trying to remove background from a captcha like image to further use for OCR. I tried using ImageMagick (through ShellExecute) but unfortunately that didn't get me the result I need. I did some googling and it seems the best way to compare colors is CIELAB. I was trying to find anything similar done in AutoIt but could not find anything so I'm not even sure it is possible.

I did find this from Mr. @Jchd. But again, not sure how precise this is compared to the CIELAB calculations.

then the "simple" colorimetric distance separing them is:
Local $ColorDist = Sqrt(($r2 - $r1) ^ 2 + ($g2 - $g1) ^ 2 + ($b2 - $b1) ^ 2)

I also found this from Mr. @Melba23 which compares Luminosity only. Apparently the Luminosity is calculated from RGB values.

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <Color.au3>

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\150.bmp");<-- Enter Image file here

If @error Then
    MsgBox(0,"","File not loaded")
    Exit
EndIf

Global $GuiSizeX = _GDIPlus_ImageGetWidth($hImage)
Global $GuiSizeY = _GDIPlus_ImageGetHeight($hImage)

$hGui = GUICreate("Change Colours", $GuiSizeX, $GuiSizeY, 100, 100)
GUISetState()

; Create Double Buffer, so the doesn't need to be repainted on PAINT-Event
$hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGui)
$hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
$hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
;End Double Buffer add-in 1 of 3

_GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, 0, 0, $GuiSizeX, $GuiSizeY)

; Create Double Buffer, so the doesn't need to be repainted on PAINT-Event
GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
_GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
;End Double Buffer add-in 2 of 3

Local $hBitmap = Image_BandW($hBMPBuff, 0, 0, $GuiSizeX, $GuiSizeY, 185) ; <<<<<<<<<<<<<<<<<<< The luminosity value is set here - default is 127

If _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\TestWrite1.bmp") =  True Then; Transparency file
    ShellExecute(@ScriptDir & "\TestWrite1.bmp")
Else
    MsgBox(0,"","File not created")
EndIf

WinActivate($hGui)

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            close()
    EndSwitch
WEnd

;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    ; The sequencial order of these two commands is important.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGui, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME)); , $RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc  ;==>MY_PAINT

Func close()
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    Exit
EndFunc  ;==>close


Func Image_BandW($hImage2, $iStartPosX = 0, $iStartPosY = 0, $GuiSizeX = Default, $GuiSizeY = Default, $iLumin = 127)
    Local $hBitmap1, $Reslt, $width, $height, $stride, $format, $Scan0, $v_Buffer, $v_Value, $iIW, $iIH
    $iIW = _GDIPlus_ImageGetWidth($hImage2)
    $iIH = _GDIPlus_ImageGetHeight($hImage2)
    If $GuiSizeX = Default Or $GuiSizeX > $iIW - $iStartPosX Then $GuiSizeX = $iIW - $iStartPosX
    If $GuiSizeY = Default Or $GuiSizeY > $iIH - $iStartPosY Then $GuiSizeY = $iIH - $iStartPosY
    $hBitmap1 = _GDIPlus_BitmapCloneArea($hImage2, $iStartPosX, $iStartPosY, $GuiSizeX, $GuiSizeY, $GDIP_PXF32ARGB)
    
    ProgressOn("Making a color Transparent", "The image is being processed.", "0 percent", -1, -1, 16)

    $Reslt = _GDIPlus_BitmapLockBits($hBitmap1, 0, 0, $GuiSizeX, $GuiSizeY, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)
    
    ;Get the returned values of _GDIPlus_BitmapLockBits ()
    $width = DllStructGetData($Reslt, "width")
    $height = DllStructGetData($Reslt, "height")
    $stride = DllStructGetData($Reslt, "stride")
    $format = DllStructGetData($Reslt, "format")
    $Scan0 = DllStructGetData($Reslt, "Scan0")
    For $i = 0 To $GuiSizeX - 1
        For $j = 0 To $GuiSizeY - 1
            $v_Buffer = DllStructCreate("dword", $Scan0 + ($j * $stride) + ($i * 4))
            $v_Value = DllStructGetData($v_Buffer, 1)
            
            Local $nLumin = (_ColorGetRed($v_Value) * 0.3) + (_ColorGetGreen($v_Value) * 0.59) + (_ColorGetBlue($v_Value) * 0.11)
            If $nLumin > $iLumin Then
                DllStructSetData($v_Buffer, 1, 0xFFFFFFFF); Sets to white
            Else
                DllStructSetData($v_Buffer, 1, 0xFF000000); Sets to black
            EndIf
            
        Next
        ProgressSet(Int(100 * $i / ($GuiSizeX)), Int(100 * $i / ($GuiSizeX)) & " percent")
        Next
    _GDIPlus_BitmapUnlockBits($hBitmap1, $Reslt)
    ProgressOff()
    Return $hBitmap1
EndFunc  ;==>Image_BandW

Now, my question is: what is the best way to compare colors to remove all other colors and for the result image to be usable for OCR? Can Melba's script be updated to what Mr. @jchd posted for it work reliably?

I'm not sure how to go about it so I figured I'd rather ask before I spend any unreasonable time on it without knowing if the outcome would be worth it.

Thanks for any help I can get!

Seminko

Edited by Seminko

Share this post


Link to post
Share on other sites



Seminko,

Quote

I'm trying to remove background from a captcha like image to further use for OCR      (my bold)

So how does this not fall foul of the Forum rules?

M23

 


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
1 minute ago, Melba23 said:

Seminko,

So how does this not fall foul of the Forum rules?

M23

 

Dang it... I guess I have to read those more often.

To clarify, I'm not doing anything malicious but I understand that the forum needs to cover their behinds.

So yea, sorry about that and the thread can be closed I guess.

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.