Image thresholding process

Just starting out? Need help? Post your questions and find answers here.
ashz
New User
New User
Posts: 4
Joined: Wed Jan 16, 2013 8:23 pm

Image thresholding process

Post by ashz »

How can I perform a Otsu's method or another image thresholding process using Purebasic (source code wil be great).

Thx
citystate
Enthusiast
Enthusiast
Posts: 638
Joined: Sun Feb 12, 2006 10:06 pm

Re: Image thresholding process

Post by citystate »

Hi ashz,

what do you have so far? we're happy to help out solving specific problems you encounter :)
there is no sig, only zuul (and the following disclaimer)

WARNING: may be talking out of his hat
User avatar
Demivec
Addict
Addict
Posts: 4283
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Image thresholding process

Post by Demivec »

ashz wrote:How can I perform a Otsu's method or another image thresholding process using Purebasic (source code wil be great).
Normally you would provide what you have worked out so far and individuals will assist you if you get stuck. I was intrigued by your question though and created an example (not perfect) using Otsu's method which I translated from some java code found here.

You load the picture and it will resize it to fit the square view windows, convert it to greyscale and then show the b/w image using Otsu's method for calculating the threshold. If you are curious you can move the trackbar and see if there are other threshold values that would have been better.

Code: Select all

UseJPEGImageDecoder()
UsePNGImageDecoder()
#True = 1
#False = 0

Procedure greyscale(img, Array srcData(1))
  Protected width, height, x, y, gray, pixel
  If Not IsImage(img) : ProcedureReturn #False : EndIf
  
  StartDrawing(ImageOutput(img))
    width = ImageWidth(img) - 1
    height = ImageHeight(img) - 1
    For y = 0 To height
      For x = 0 To width
        pixel = Point(x, y)
        grey = Red(pixel) * 77    ; 0.2989 * 256 = 76.5184
        grey + Green(pixel) * 150 ; 0.5870 * 256 = 150.2720
        grey + Blue(pixel) * 29   ; 0.1140 * 256 = 29.1840
        grey = grey >> 8          ; / 256
        Plot(x, y, RGB(grey, grey, grey))
        srcData(y * (width + 1) + x) = grey
      Next
    Next
  StopDrawing()
  
  ProcedureReturn #True
EndProcedure

Procedure createImageWithThreshold(img, Array srcData(1), threshold)
  Protected width, height, x, y, gray, pixel
  If Not IsImage(img) : ProcedureReturn #False : EndIf
  
  StartDrawing(ImageOutput(img))
    width = ImageWidth(img) - 1
    height = ImageHeight(img) - 1
    For y = 0 To height
      For x = 0 To width
        pixel = srcData(y * (width + 1) + x)
        If pixel >= threshold
          pixel = RGB(255, 255, 255)
        Else 
          pixel = RGB(0, 0, 0)
        EndIf 
        
        Plot(x, y, pixel)
      Next
    Next
  StopDrawing()
  
  ProcedureReturn #True
EndProcedure

Procedure otsu_threashold(Array srcData(1))
  ;The input is an array of bytes, srcData that stores the greyscale image
  
  ;Calculate histogram
  Protected srcDataLength = ArraySize(srcData()), ptr, h
  Protected Dim histData($FF)
  
  While ptr < srcDataLength
    h = $FF & srcData(ptr)
    histData(h) + 1
    ptr + 1
  Wend
  
  Protected.f sum, sumB, varMax, varBetween, mB, mF
  Protected wB, wF, threshold
  
  For t = 0 To $FF
    sum + t * histData(t)
  Next
  
  For t = 0 To $FF
    wB + histData(t)         ;Weight Background
    If wB = 0: Continue: EndIf
    
    wF = srcDataLength - wB  ;Weight Foreground
    If wF = 0: Break: EndIf
    
    sumB + t * histData(t)
    mB = sumB / wB           ;Mean Background
    mF = (sum - sumB) / wF   ;Mean Foreground
    
    ;Calculate Between Class Variance
    varBetween = (mB - mF) * (mB - mF) * wB * wF

    ;Check If new maximum Found
    If varBetween > varMax
      varMax = varBetween
      threshold = t
    EndIf 
  Next
  ProcedureReturn threshold
EndProcedure

Enumeration
  ;windows
  #main_win = 0
  ;gadgets
  #load_btn = 0
  #sourceImage_img
  #resultImage_img
  #threshold_trk
  #threshold_txt
  ;images
  #originalImage = 0
  #thresholdImage
EndEnumeration

#DisplayWidth = 250
#DisplayHeight = 250

OpenWindow(#main_win, 0, 0, 530, 350, "Otsu Threshold", #PB_Window_SystemMenu)
ButtonGadget(#load_btn, 0, 0, 100, 20, "Load Picture")
ImageGadget(#sourceImage_img, 10, 30, #DisplayWidth, #DisplayHeight, 0)
ImageGadget(#resultImage_img, 20 + #DisplayWidth, 30, #DisplayWidth, #DisplayHeight, 0)
TextGadget(#threshold_txt, 20 + #DisplayWidth - 55, 50 + #DisplayHeight, 55, 20, "Threshold:")
TrackBarGadget(#threshold_trk, 20 + #DisplayWidth, 50 + #DisplayHeight, 255, 20, 0, 255)

Define Event, EventGadget, FileName.s, threshold
Dim srcData(#DisplayWidth * #DisplayHeight - 1)
Repeat
  Event = WaitWindowEvent(10)
  Select Event
    Case #PB_Event_Gadget
      EventGadget = EventGadget()
      Select EventGadget
        Case #load_btn
          ;load picture
          FileName = OpenFileRequester("Select source image:", "C:\*.*", "Image|*.png;*.jpg;*.bmp|All Files (*.*)|*.*", 0)
          If FileName
            If LoadImage(#originalImage, FileName)
              If ImageWidth(#originalImage) <> #DisplayWidth Or ImageHeight(#originalImage) <> #DisplayHeight
                ResizeImage(#originalImage, #DisplayWidth, #DisplayHeight)
              EndIf 
              
              SetGadgetState(#sourceImage_img, ImageID(#originalImage))
              ;convert to greyscale
              greyscale(#originalImage, srcData())
               
              ;get threshold
              threshold = otsu_threashold(srcData())
              CopyImage(#originalImage, #thresholdImage)
              
              ;create image based on threshold
              createImageWithThreshold(#thresholdImage, srcData(), threshold)
              SetGadgetState(#resultImage_img, ImageID(#thresholdImage))
              SetGadgetState(#threshold_trk, threshold)
              
            EndIf
          EndIf 
        Case #threshold_trk
          If GetGadgetState(#threshold_trk) <> threshold
            threshold = GetGadgetState(#threshold_trk)
            CopyImage(#originalImage, #thresholdImage)
            
            ;create image based on threshold
            createImageWithThreshold(#thresholdImage, srcData(), threshold)
            SetGadgetState(#resultImage_img, ImageID(#thresholdImage))
          EndIf 
            
      EndSelect
  EndSelect

Until Event = #PB_Event_CloseWindow
Post Reply