PureBasic Interface to OpenCV

Developed or developing a new product in PureBasic? Tell the world about it.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: PureBasic Interface to OpenCV

Post by JHPJHP »

Updated the Main and World packages:
- added 1 example
-- cv_pixel_spread.pb: apply a pixel spread effect to an image

NB*: Press the Spacebar to animate the pixel spread.

Image
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: PureBasic Interface to OpenCV

Post by JHPJHP »

MLS Deformation: Coming Soon
- cv_MLS_deformation.pb: Moving Least Squares (MLS) image deformation; includes three transformation functions: Rigid, Similarity, and Affine

Based on script from here.

Demo JavaScript version provided by the original author: Warp Image.

Additional Information: Image Deformation Using Moving Least Squares.

Image Image
Last edited by JHPJHP on Sun Jun 25, 2017 5:05 pm, edited 7 times in total.
LiK137
Enthusiast
Enthusiast
Posts: 279
Joined: Wed Jun 23, 2010 5:13 pm

OpenCV Img Brightness/Contrast Gray but Color

Post by LiK137 »

Hi,
The original example cv_histogram_2.pb from OpenCV 3.1 affecting image brightness/Contrast is working with only Image Gray mode.
So

Code: Select all

 *image.IplImage = cvLoadImage(ImageFile, #CV_LOAD_IMAGE_ANYCOLOR | #CV_LOAD_IMAGE_ANYDEPTH) ;#CV_LOAD_IMAGE_GRAYSCALE)
causing fail on

Code: Select all

cvCalcHist(@*clone, *histogram, #False, #Null)
line

Code: Select all

IncludeFile "includes/cv_functions.pbi"

Global openCV, *save.IplImage, exitCV, lpPrevWndFunc, nBrightness, nContrast, Dim lut.b(256)

#CV_WINDOW_NAME = "PureBasic Interface to OpenCV"
#CV_DESCRIPTION = "Calculates a histogram based on brightness and contrast levels." + #LF$ + #LF$ +
                  "- TRACKBAR 1: Adjust the brightness." + #LF$ + #LF$ +
                  "- TRACKBAR 2: Adjust the contrast."

Procedure WindowCallback(hWnd, Msg, wParam, lParam)
  Select Msg
    Case #WM_COMMAND
      Select wParam
        Case 1
          openCV = #True
          keybd_event_(#VK_ESCAPE, 0, 0, 0)
        Case 2
          FileName.s = SaveCVImage()

          If FileName
            params.SAVE_INFO

            Select LCase(GetExtensionPart(FileName))
              Case "bmp", "dib"
              Case "jpeg", "jpg", "jpe"
                params\paramId = #CV_IMWRITE_JPEG_QUALITY
                params\paramValue = 95
              Case "jp2"
              Case "png"
                params\paramId = #CV_IMWRITE_PNG_COMPRESSION
                params\paramValue = 3
              Case "ppm", "pgm", "pbm"
                params\paramId = #CV_IMWRITE_PXM_BINARY
                params\paramValue = 1
              Case "sr", "ras"
              Case "tiff", "tif"
              Default
                Select SelectedFilePattern()
                  Case 0
                    FileName + ".bmp"
                  Case 1
                    FileName + ".jpg"
                    params\paramId = #CV_IMWRITE_JPEG_QUALITY
                    params\paramValue = 95
                  Case 2
                    FileName + ".jp2"
                  Case 3
                    FileName + ".png"
                    params\paramId = #CV_IMWRITE_PNG_COMPRESSION
                    params\paramValue = 3
                  Case 4
                    FileName + ".ppm"
                    params\paramId = #CV_IMWRITE_PXM_BINARY
                    params\paramValue = 1
                  Case 5
                    FileName + ".sr"
                  Case 6
                    FileName + ".tiff"
                EndSelect
            EndSelect
            cvSaveImage(FileName, *save, @params)
          EndIf
        Case 10
          keybd_event_(#VK_ESCAPE, 0, 0, 0)
      EndSelect
    Case #WM_DESTROY
      exitCV = #True
  EndSelect
  ProcedureReturn CallWindowProc_(lpPrevWndFunc, hWnd, Msg, wParam, lParam)
EndProcedure

ProcedureC CvMouseCallback(event, x.l, y.l, flags, *param.USER_INFO)
  Select event
    Case #CV_EVENT_RBUTTONDOWN
      *save = *param\uPointer1
      DisplayPopupMenu(0, *param\uValue)
  EndSelect
EndProcedure

Procedure UpdateBrightnessContrast()
  Dim lut.b(256)
  
  brightness = nBrightness - 100
  contrast = nContrast - 100

  If contrast > 0
    delta.d = 127 * contrast / 100
    a.d = 255 / (255 - delta * 2)
    b.d = a * (brightness - delta)
  Else
    delta.d = -128 * contrast / 100
    a.d = (256 - delta * 2) / 255
    b.d = a * brightness + delta
  EndIf

  For i = 0 To 256 - 1
    v = Round(a * i + b, #PB_Round_Nearest)

    If v < 0 : v = 0 : EndIf
    If v > 255 : v = 255 : EndIf

    lut(i) = v
  Next
EndProcedure

ProcedureC CvTrackbarCallback1(pos)
  nBrightness = pos
  UpdateBrightnessContrast()
  keybd_event_(#VK_RETURN, 0, 0, 0)
EndProcedure

ProcedureC CvTrackbarCallback2(pos)
  nContrast = pos
  UpdateBrightnessContrast()
  keybd_event_(#VK_RETURN, 0, 0, 0)
EndProcedure

Procedure OpenCV(ImageFile.s)
  If FileSize(ImageFile) > 0
    cvNamedWindow(#CV_WINDOW_NAME, #CV_WINDOW_AUTOSIZE)
    window_handle = cvGetWindowHandle(#CV_WINDOW_NAME)
    *window_name = cvGetWindowName(window_handle)
    lpPrevWndFunc = SetWindowLongPtr_(window_handle, #GWL_WNDPROC, @WindowCallback())

    If CreatePopupImageMenu(0, #PB_Menu_ModernLook)
      MenuItem(1, "Open")
      MenuBar()
      MenuItem(2, "Save")
      MenuBar()
      MenuItem(10, "Exit")
    EndIf
    hWnd = GetParent_(window_handle)
    iconCV = LoadImage_(GetModuleHandle_(0), @"icons/opencv.ico", #IMAGE_ICON, 35, 32, #LR_LOADFROMFILE)
    SendMessage_(hWnd, #WM_SETICON, 0, iconCV)
    wStyle = GetWindowLongPtr_(hWnd, #GWL_STYLE)
    SetWindowLongPtr_(hWnd, #GWL_STYLE, wStyle & ~(#WS_MAXIMIZEBOX | #WS_MINIMIZEBOX | #WS_SIZEBOX))
    Debug "OK0"
    *image.IplImage = cvLoadImage(ImageFile, #CV_LOAD_IMAGE_GRAYSCALE);#CV_LOAD_IMAGE_ANYCOLOR );| #CV_LOAD_IMAGE_ANYDEPTH);, #CV_LOAD_IMAGE_GRAYSCALE)
    Debug "OK1"
    dtWidth = DesktopWidth(0)
    dtHeight = DesktopHeight(0)

    If *image\width >= dtWidth - 100 Or *image\height >= dtHeight - (100 + 48 + 42)
      iWidth = dtWidth - 100
      iRatio1.d = iWidth / *image\width
      iHeight = dtHeight - (100 + 48 + 42)
      iRatio2.d = iHeight / (*image\height)

      If iRatio1 < iRatio2
        iWidth = *image\width * iRatio1
        iHeight = *image\height * iRatio1
      Else
        iWidth = *image\width * iRatio2
        iHeight = *image\height * iRatio2
      EndIf
      cvResizeWindow(#CV_WINDOW_NAME, iWidth, iHeight + 48 + 42)
      PokeL(@*size, iWidth) : PokeL(@*size + 4, iHeight)
      *resize.IplImage = cvCreateImage(*size, #IPL_DEPTH_8U, *image\nChannels)
      cvResize(*image, *resize, #CV_INTER_AREA)
    Else
      cvResizeWindow(#CV_WINDOW_NAME, *image\width, *image\height + 48 + 42)
      *resize.IplImage = cvCloneImage(*image)
    EndIf
    cvMoveWindow(#CV_WINDOW_NAME, 20, 20)
    ToolTip(window_handle, #CV_DESCRIPTION)
    
    Debug "OK2"
    
    If *resize\width > 200 And *resize\height > 200
      nBrightness = 100 : nContrast = 100
      cvCreateTrackbar("Brightness", #CV_WINDOW_NAME, @nBrightness, 201, @CvTrackbarCallback1())
      cvCreateTrackbar("Contrast", #CV_WINDOW_NAME, @nContrast, 201, @CvTrackbarCallback2())
      *clone.IplImage = cvCloneImage(*resize)
      PokeL(@*size, 193) : PokeL(@*size + 4, 100)
      *hist.IplImage = cvCreateImage(*size, #IPL_DEPTH_8U, 1)
      cvGetSize(@*get_size, *resize)
      *gray.IplImage = cvCreateImage(*get_size, #IPL_DEPTH_8U, 1)
      *color.IplImage = cvCreateImage(*get_size, #IPL_DEPTH_8U, 3)
      *lut = cvCreateMatHeader(1, 256, CV_MAKETYPE(#CV_8U, 1))
      bins = 64 : Dim range.f(2) : range(0) = 0 : range(1) = 256
      *ranges.FLOAT : PokeL(@*ranges, @range())
      *histogram.CvHistogram = cvCreateHist(1, @bins, #CV_HIST_ARRAY, @*ranges, #True)
      cvSetData(*lut, @lut(), 0)
      UpdateBrightnessContrast()
      *param.USER_INFO = AllocateMemory(SizeOf(USER_INFO))
      *param\uPointer1 = *gray
      *param\uValue = window_handle
      cvSetMouseCallback(*window_name, @CvMouseCallback(), *param)
      color1.CvScalar : color1\val[0] = 0 : color1\val[1] = 0 : color1\val[2] = 0 : color1\val[3] = 0
      color2.CvScalar : color2\val[0] = 0 : color2\val[1] = 255 : color2\val[2] = 255 : color2\val[3] = 0
      value1.CvScalar : value1\val[0] = 255 : value1\val[1] = 255 : value1\val[2] = 255 : value1\val[3] = 0
      value2.CvScalar : value2\val[0] = 0 : value2\val[1] = 0 : value2\val[2] = 0 : value2\val[3] = 0
      rect.CvRect : rect\x = 20 : rect\y = 20 : rect\width = 193 : rect\height = 100
      r.CvRect : r\x = 19 : r\y = 19 : r\width = 193 + 2 : r\height = 100 + 2
      
      Debug "OK3"

      Repeat
        If *resize
          cvSetZero(*clone)
          Debug "OK4"
          cvLUT(*resize, *clone, *lut)
          Debug "OK5"
          cvCalcHist(@*clone, *histogram, #False, #Null)
          Debug "OK6"
          cvGetMinMaxHistValue(*histogram, #Null, @max_value.f, #Null, #Null)
          Debug "OK7"
          cvConvertScale(*histogram\bins, *histogram\bins, *hist\height / max_value, 0)
          Debug "OK8"
          cvSet(*hist, @value1, #Null)
          bin = Round(*hist\width / bins, #PB_Round_Nearest)
          
          
          For i = 0 To bins - 1
            x1 = i * bin
            y1 = *hist\height
            x2 = (i + 1) * bin
            y2 = *hist\height - Round(cvGetReal1D(*histogram\bins, i), #PB_Round_Nearest)
            PokeL(@*pt1, x1) : PokeL(@*pt1 + 4, y1)
            PokeL(@*pt2, x2) : PokeL(@*pt2 + 4, y2)
            cvRectangle(*hist, *pt1, *pt2, @color1, #CV_FILLED, #CV_AA, #Null)
          Next
          cvCopy(*clone, *gray, #Null)
          cvSetImageROI(*gray, @rect)
          cvAndS(*gray, @value2, *gray, #Null)
          cvAdd(*gray, *hist, *gray, #Null)
          cvResetImageROI(*gray)
          cvCvtColor(*gray, *color, #CV_GRAY2BGR, 1)
          cvRectangleR(*color, @r, @color2, 2, #CV_AA, #Null)
          cvShowImage(#CV_WINDOW_NAME, *color)
          keyPressed = cvWaitKey(0)
        EndIf
      Until keyPressed = 27 Or exitCV
      FreeMemory(*param)
      cvReleaseImage(@*resize)
      cvReleaseImage(@*image)
      cvDestroyAllWindows()

      If openCV
        openCV = #False
        exitCV = #False
        OpenCV(OpenCVImage())
      EndIf
    Else
      MessageRequester(#CV_WINDOW_NAME, ImageFile + #LF$ + #LF$ + "... does not meet the size requirements, please try another image.", #MB_ICONERROR)
      cvReleaseHist(@*histogram)
      cvReleaseMat(@*lut)
      cvReleaseImage(@*color)
      cvReleaseImage(@*gray)
      cvReleaseImage(@*hist)
      cvReleaseImage(@*clone)
      cvReleaseImage(@*resize)
      cvReleaseImage(@*image)
      cvDestroyAllWindows()
      exitCV = #False
      OpenCV(OpenCVImage())
    EndIf
  EndIf
EndProcedure

ExamineDesktops()
OpenCV("images/building.jpg")

Thank You very much
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: PureBasic Interface to OpenCV

Post by JHPJHP »

Hi LiK137,

Your approach is all wrong, you're trying to modify a one channel histogram example that uses brightness and contrast to demonstrate the use of Lookup Tables (LUT).

Check your private message folder for an example that should answer your question.
- cv_convertscale.pb: modify the brightness and contrast levels using a scaling factor

The example also includes an absolute scaling factor that can be toggled ON / OFF using the SPACEBAR.
- set brightness and contrast to around 50 for a negative transformation
Last edited by JHPJHP on Sun Jun 25, 2017 5:06 pm, edited 3 times in total.
LiK137
Enthusiast
Enthusiast
Posts: 279
Joined: Wed Jun 23, 2010 5:13 pm

Re: PureBasic Interface to OpenCV

Post by LiK137 »

Hi JHPJHP,
Thanx very much for reply.
With Your hep I implemented Your Brightness/Contrast solution.
I liked that and ask if any for Sharpness and Exposure but not "cvSetCaptureProperty" way.

Like cvConvertScale or other calulative way is OK.

Thank Yoy very much
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: PureBasic Interface to OpenCV

Post by JHPJHP »

Hi LiK137,

After this example you are going to have to do your own Google searches...

Check your private message folder for an example that should answer your question.
- cv_sharpen.pb: Unsharp Masking (USM): Combining a blurred mask with the original image for a sharpen effect

Additional information: Unsharp masking (USM)
LiK137
Enthusiast
Enthusiast
Posts: 279
Joined: Wed Jun 23, 2010 5:13 pm

Re: PureBasic Interface to OpenCV

Post by LiK137 »

Thank You very much,
Very impressed where You get these perfect answers.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: PureBasic Interface to OpenCV

Post by JHPJHP »

Hi LiK137,

Your welcome.

In our PM you asked again about an Exposure example. While I don't have anymore time to put towards your projects, you still may be in luck...

Take a look at the already existing example cv_gamma.pb (jointly contributed by AAT); I believe Gamma Correction and Exposure Compensation are the same thing.
LiK137
Enthusiast
Enthusiast
Posts: 279
Joined: Wed Jun 23, 2010 5:13 pm

Re: PureBasic Interface to OpenCV

Post by LiK137 »

Thank You,
You are fantastic
AAT
Enthusiast
Enthusiast
Posts: 256
Joined: Sun Jun 15, 2008 3:13 am
Location: Russia

Re: PureBasic Interface to OpenCV

Post by AAT »

Hi, JHPJHP.

A small addition to OCR Tesseract.

I wanted to use a confidence level to detect the rotation of the text by 180 degrees.
Unexpectedly, I found that if in the example cv_OCR_confidence.pb to repeat several recognition cycles, then the confidence level increases even for incorrectly recognized text. For example for this picture

Image

To exclude this effect, I added a prototype function to the file pb_tesseract.pbi and used it in the procedure GetConfidence.
pb_tesseract.pbi

Code: Select all

ImportC "libtesseract302.lib"
...
	TessBaseAPIClearAdaptiveClassifier(*TessBaseAPI)
...
cv_OCR_confidence.pb

Code: Select all

Procedure GetConfidence(*confidence.IplImage, hApi, iLevel)
....
  threshold.d = cvThreshold(*gray, *bin, 10, 255, #CV_THRESH_OTSU)
  TessBaseAPIClearAdaptiveClassifier(hAPI)
  TessBaseAPISetImage(hApi, *bin\imageData, *bin\width, *bin\height, 1, *bin\widthStep)
...
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: PureBasic Interface to OpenCV

Post by JHPJHP »

Hi AAT,

Thank you for the update to your OCR example.

---------------------------------------------------------------------

Updated (Main and World interfaces):
- updated 1 example
-- cv_OCR_confidence.pb (pb_tesseract.pbi)
- renamed 1 example
-- cv_sharpen.pb to cv_sharpen_2.pb
- added three examples
-- cv_convertscale.pb: modify the brightness and contrast levels using a scaling factor
-- cv_sharpen_1.pb: Unsharp masking (USM): Combining a blurred mask with the original image for a sharpen effect
-- cv_MLS_deformation.pb: Moving Least Squares (MLS) image deformation; includes three transformation functions: Rigid, Similarity, and Affine
--- Affine transformation not available in the World packages

NOTE: The Mouse Callback Procedure for many of the Main and World package examples has been updated.

Moving Least Squares (MLS): cv_MLS_deformation.pb

Anchor Points: Static points placed around the border to pin the frame in-place (YELLOW).
Control Point: Dynamic point used to either pin an area in-place or expanded to Deform Points (BLUE).
Deform Points: Dynamic points used to either deform an area or reset to a Control Point (GREEN connecting RED).

Points are calculated relative to the original image, which is why it can be more accurate to add all the Control Points before executing a deformation.
Alternately, you can switch to the original image to place additional Control Points, but it is not required.


INFORMATION:
- Control Points and Deform Points can be selected, moved, and deleted
- a minimum of 2 points are required to execute a deformation, with at least 1 being a set of Deform Points
- adjusting the grid size will directly affect the deformation algorithms

INSTRUCTIONS (simple demo):
1. Add 5 Control Points (expanded to Deform Points in steps 2 - 4).
-- left eye, right eye, nose, left-side mouth, right-side mouth
2. Drag the "eyes and nose" Control Points DOWN approximately 1cm.
3. Drag the "left-side mouth" Control Point UP-LEFT approximately 1cm.
4. Drag the "right-side mouth" Control Point UP-RIGHT approximately 1cm.
5. Press the [A - KEY] to set Anchor Points.
6. Press the [G - KEY] to toggle the grid ON / OFF.
-- change the TRACKBAR setting to modify the deformation
7. Press the [P - KEY] to turn OFF points.
8. Press the [T - KEY] to switch between the 3 transformations.
-- subtle changes become more drastic with modified settings
9. Press the SPACEBAR to toggle between the original and deformed image.
Last edited by JHPJHP on Sun Jun 25, 2017 5:07 pm, edited 3 times in total.
AAT
Enthusiast
Enthusiast
Posts: 256
Joined: Sun Jun 15, 2008 3:13 am
Location: Russia

Re: PureBasic Interface to OpenCV

Post by AAT »

Hi, JHPJHP!

I looked at your new examples, they are brilliant!
I'm afraid to even think how much time and effort you spent on them. Thank you so much for your wonderful work!
The example pb_sharpen1.pb was very handy and helped me to recognize images with datamatrix code.

I'm sorry, I did not see your message again on time. Can you send me messages to the mailbox?
I will send it to you in PM.

Best regards!
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: PureBasic Interface to OpenCV

Post by JHPJHP »

Hi AAT,

Thank you for your kind words.

----------------------------------------------------

Updated the Main and World packages:
- renamed 2 examples
-- cv_distortion_1.pb to cv_deformation_1.pb
-- cv_distortion_2.pb to cv_deformation_2.pb
- updated 3 examples
-- cv_deformation_1.pb, cv_deformation_2.pb
-- cv_MLS_deformation.pb
--- added three options
---- [ L ] KEY: Load points files
---- [ R ] KEY: Run deformed animation
---- [ S ] KEY: Save points files
--- added 1 set of points files
- formatted all tooltips

----------------------------------------------------

DeformMLS Image :: PureBasic / OpenCV Application :: Windows :: 32 bit (see the first post under APPLICATIONS)
- does not include the Affine Transformation found in the Main downloads (excluded to keep size down)

Anchor Points: Static points placed around the border to pin the frame in-place (YELLOW).
Control Point: Dynamic point used to either pin an area in-place or expanded to Deform Points (BLUE).
Deform Points: Dynamic points used to either deform an area or reset to a Control Point (GREEN connecting RED).

Points are calculated relative to the original image, which is why it can be more accurate to add all the Control Points before executing a deformation.
Alternately, you can switch to the original image to place additional Control Points, but it is not required.


See the Context Menu for available options, including help tooltips.

INSTRUCTIONS (using shortcut keys):
1. Press the [ L ] KEY to load a set of points files.
-- /points/joker.src
2. Press the [ R ] KEY to run the deformed animation.
3. Press the [ G ] KEY to show the grid.
4. Press the [ P ] KEY to show the points.
5. Press the [ A ] Key to remove the Anchor Points.
6. Press the [ T ] Key to change the transformation.
7. Press ENTER to reset the image.
8. Use the MOUSE to add Control Points.
9. Use the MOUSE to drag Control Points into Deform Points.
...

Additional Information: Moving Least Squares (MLS) Deformation
Last edited by JHPJHP on Fri Jun 30, 2017 2:40 am, edited 1 time in total.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: PureBasic Interface to OpenCV

Post by JHPJHP »

Updated APPLICATIONS (located in the first post):
- updated 2 applications
-- DeformMLS, DyLibPatcher
- renamed 1 application
-- DeformMLS to DeformMLS_2T
- added 1 application
-- DeformMLS_3T

The new DeformMLS_3T application includes the Affine Transformation.
- compare the two packages; with and without legacy Functions

NOTE: All packages contain full source code.

The DeformMLS applications only require the binaries folder, but the images and points folders should also be included for the following demonstration.

Use either the Context Menu or Shortcut Keys:
1. Press the [ L ] KEY to load a set of points files.
-- /points/joker.src
2. Press the [ R ] KEY to run the deformed animation.

NB*: See the previous post for a more detailed set of instructions.
AAT
Enthusiast
Enthusiast
Posts: 256
Joined: Sun Jun 15, 2008 3:13 am
Location: Russia

Re: PureBasic Interface to OpenCV

Post by AAT »

Hi!

If you have a possibility of manual focusing of the image of your webcam, you can expreiment with contrast-detect based focusing.
In this example the first derivative by X of the selected region of gray image is calculated.
Have fun!

Code: Select all

IncludeFile "includes/cv_functions.pbi"

Global lpPrevWndFunc

#CV_WINDOW_NAME = "PureBasic Interface to OpenCV"
#CV_DESCRIPTION = "Contrast-detect based focusing." + #LF$

#SensorWidth = 50
#SensorHeight = 50

Procedure WindowCallback(hWnd, uMsg, wParam, lParam)
  Shared exitCV

  Select uMsg
    Case #WM_COMMAND
      Select wParam
        Case 10
          exitCV = #True
      EndSelect
    Case #WM_DESTROY
      exitCV = #True
  EndSelect
  ProcedureReturn CallWindowProc_(lpPrevWndFunc, hWnd, uMsg, wParam, lParam)
EndProcedure

Procedure CvMouseCallback(event, x.l, y.l, flags, *param.CvUserData)
  Select event
    Case #CV_EVENT_RBUTTONDOWN
      DisplayPopupMenu(0, *param\Value)
  EndSelect
EndProcedure

Repeat
  nCreate + 1
  *capture.CvCapture = cvCreateCameraCapture(#CV_CAP_ANY)
Until nCreate = 5 Or *capture

If *capture
  cvNamedWindow(#CV_WINDOW_NAME, #CV_WINDOW_AUTOSIZE)
  window_handle = cvGetWindowHandle(#CV_WINDOW_NAME)
  *window_name = cvGetWindowName(window_handle)
  lpPrevWndFunc = SetWindowLongPtr_(window_handle, #GWL_WNDPROC, @WindowCallback())

  If CreatePopupImageMenu(0, #PB_Menu_ModernLook)
    MenuItem(10, "Exit")
  EndIf
  hWnd = GetParent_(window_handle)
  iconCV = LoadImage_(GetModuleHandle_(0), @"icons/opencv.ico", #IMAGE_ICON, 35, 32, #LR_LOADFROMFILE)
  SendMessage_(hWnd, #WM_SETICON, 0, iconCV)
  wStyle = GetWindowLongPtr_(hWnd, #GWL_STYLE)
  SetWindowLongPtr_(hWnd, #GWL_STYLE, wStyle & ~(#WS_MAXIMIZEBOX | #WS_MINIMIZEBOX | #WS_SIZEBOX))
  FrameWidth = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_WIDTH)
  FrameHeight = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_HEIGHT)
  cvMoveWindow(#CV_WINDOW_NAME, 20, 20)
  ToolTip(window_handle, #CV_DESCRIPTION)
  
  *image.IplImage
  *contrsqColor.IplImage = cvCreateImage(#SensorWidth, #SensorHeight, #IPL_DEPTH_8U, 3)
  *contrsqGray.IplImage = cvCreateImage(#SensorWidth, #SensorHeight, #IPL_DEPTH_8U, 1)
  *contrsqSobel.IplImage = cvCreateImage(#SensorWidth, #SensorHeight, #IPL_DEPTH_8U, 1)
  Dim med(3)
  For i = 0 To 3
    med(i) = 0
  Next 
  *param.CvUserData = AllocateMemory(SizeOf(CvUserData))
  *param\Value = window_handle
  cvSetMouseCallback(*window_name, @CvMouseCallback(), *param)

  Repeat
    *image = cvQueryFrame(*capture)

    If *image
      framecntr.a + 1
      If (framecntr%4) = 1
        cvSetImageROI(*image, *image\width/2-#SensorWidth/2, *image\height/2-#SensorHeight/2, #SensorWidth, #SensorHeight)
        cvCopy(*image, *contrsqColor, #Null)
        cvCvtColor(*contrsqColor, *contrsqGray, #CV_BGR2GRAY, 1)
        cvResetImageROI(*image)         
        cvSmooth(*contrsqGray, *contrsqGray, #CV_GAUSSIAN, 3, 0, 0, 0)                                             
        cvSobel(*contrsqGray, *contrsqSobel, 1, 1, 3) 
        contrastMax = 0     
        For x = 0 To *contrsqSobel\width - 1
          For y = 0 To *contrsqSobel\height - 1
            contrpic = PeekA(@*contrsqSobel\imagedata\b + y * *contrsqSobel\widthStep + x)           
            If  contrpic > contrastMax
              contrastMax = contrpic
            EndIf
          Next Y
        Next X
        wrptr + 1
        If wrptr > 3
          wrptr = 0
        EndIf
        med(wrptr) = contrastMax        
        contrastMax = 0
        For i = 0 To 3
          contrastMax + med(i)       
        Next
        contrastMax/4    
      EndIf      
      cvRectangle(*image, *image\width/2-#SensorWidth/2, *image\height/2-#SensorHeight/2, *image\width/2+#SensorWidth/2, *image\height/2+#SensorHeight/2, 0, 250, 250, 0, 1, #CV_AA, 0)
      cvRectangle(*image, 10, *image\height-265, 30, *image\height-10, 0, 0, 0, 0, #CV_FILLED, #CV_AA, #Null)    
      cvRectangle(*image, 10, *image\height-10-contrastMax, 30, *image\height-10, 0, 250, 250, 0, #CV_FILLED, #CV_AA, #Null)  
      cvShowImage(#CV_WINDOW_NAME, *image)
      keyPressed = cvWaitKey(1)
    EndIf
  Until keyPressed = 27 Or exitCV
  FreeMemory(*param)
  cvDestroyAllWindows()
  cvReleaseCapture(@*capture)
Else
  MessageRequester(#CV_WINDOW_NAME, "Unable to connect webcam - operation cancelled.", #MB_ICONERROR)
EndIf
Locked