PureBasic Interface to OpenCV
Re: PureBasic Interface to OpenCV
Hi AAT, RSBasic,
Thank you for reviewing the previous example and pointing out the potential problem.
-----------------------------------------
Updated:
- fix the problem mentioned in the previous post
- renamed 1 example
-- cv_steganography.pb to cv_steganography_text.pb
- added 2 examples
-- cv_steganography_image_1.pb, cv_steganography_image_2.pb
Unlike the example cv_steganography_text.pb which requires a comparison image to decode the hidden message, the following examples use the LSB (Least Significant Bit) method.
- cv_steganography_image_1.pb: conceals an image within a larger image
- cv_steganography_image_2.pb: extracts the hidden image
NOTE:
- the first example starts with a defaulted embedded image
- use the context menu to change the hidden image or save the completed image
- if needed the imbedded image will be resized to fit the main image: Width x Height x 3 (channels) x 8 (LSB)
- PIP in the 1st example shows the embedded image, but is not included in the saved image
NB*: The Steganography examples require that the hidden binary data is saved in a lossless image format: defaulted to PNG (Portable Network Graphics).
			
			
									
									Thank you for reviewing the previous example and pointing out the potential problem.
-----------------------------------------
Updated:
- fix the problem mentioned in the previous post
- renamed 1 example
-- cv_steganography.pb to cv_steganography_text.pb
- added 2 examples
-- cv_steganography_image_1.pb, cv_steganography_image_2.pb
Unlike the example cv_steganography_text.pb which requires a comparison image to decode the hidden message, the following examples use the LSB (Least Significant Bit) method.
- cv_steganography_image_1.pb: conceals an image within a larger image
- cv_steganography_image_2.pb: extracts the hidden image
NOTE:
- the first example starts with a defaulted embedded image
- use the context menu to change the hidden image or save the completed image
- if needed the imbedded image will be resized to fit the main image: Width x Height x 3 (channels) x 8 (LSB)
- PIP in the 1st example shows the embedded image, but is not included in the saved image
NB*: The Steganography examples require that the hidden binary data is saved in a lossless image format: defaulted to PNG (Portable Network Graphics).
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: PureBasic Interface to OpenCV
Optimized the examples cv_steganography_image_1.pb, cv_steganography_image_2.pb.
- added two Macros
-- REPLACE_BIT, EXTRACT_BIT
NB*: Both examples execute much faster with the above change.
-----------------------------------------------------------
Updated the examples cv_steganography_image_1.pb, cv_steganography_image_2.pb.
When embedding some images the last 100 or so pixels wouldn't transfer all three channels correctly due to an alignment issue.
I remembered the example cv_encode_decode.pb where an image is encoded into a single row of data, then decoded back into the standard format; applying this technique fixed the problem.
-----------------------------------------------------------
I figured out the previous alignment issue without having to encode / decode the image, but kept the current method because it offers better security from third party steganalysis tools.
- I've updated the code to include the changes as well as some additional optimizations
			
			
									
									- added two Macros
-- REPLACE_BIT, EXTRACT_BIT
NB*: Both examples execute much faster with the above change.
-----------------------------------------------------------
Updated the examples cv_steganography_image_1.pb, cv_steganography_image_2.pb.
When embedding some images the last 100 or so pixels wouldn't transfer all three channels correctly due to an alignment issue.
I remembered the example cv_encode_decode.pb where an image is encoded into a single row of data, then decoded back into the standard format; applying this technique fixed the problem.
-----------------------------------------------------------
I figured out the previous alignment issue without having to encode / decode the image, but kept the current method because it offers better security from third party steganalysis tools.
- I've updated the code to include the changes as well as some additional optimizations
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: PureBasic Interface to OpenCV
Can anyone help me with my code?
This code make 3 frames from WebCam, but why on different memory adresses?
			
			
									
									
						Code: Select all
IncludeFile "includes/cv_functions.pbi"
EnableExplicit
UseJPEGImageDecoder()
UseJPEGImageEncoder()
Procedure.i get_frame(quality.i)
  Protected rtrn.i
  Protected *capture.CvCapture
  ;cvSetCaptureProperty(*capture.CvCapture, #CV_CAP_PROP_FRAME_WIDTH, 320)
  ;cvSetCaptureProperty(*capture.CvCapture, #CV_CAP_PROP_FRAME_HEIGHT, 240)
  *capture.CvCapture = cvCreateCameraCapture(0)
  If *capture
    Protected *image.IplImage
    *image = cvQueryFrame(*capture)
    If *image
      ;cvFlip(*image, #Null, 1)
      ;cvSaveImage("D:\img.jpg", *image, @params)
      Protected params.SAVE_INFO
      params\paramId = #CV_IMWRITE_JPEG_QUALITY
      params\paramValue = quality
      Protected *mat.CvMat = cvEncodeImage(".jpg", *image, @params)
      If CatchImage(0, *mat\ptr, *mat\cols)
        Protected *imgbuf = EncodeImage(0, #PB_ImagePlugin_JPEG)
        If *imgbuf
          rtrn = *imgbuf
        Else
          Debug "Encode Image Failure!"
          rtrn = -4
        EndIf
      Else
        Debug "Catch Image Failure!"
        rtrn = -3
      EndIf
      cvReleaseMat(@*mat)
      ;cvReleaseImage(@*image)
    Else
      Debug "Query Frame Failure!"
      rtrn = -2
    EndIf
    cvReleaseCapture(@*capture)
  Else
    Debug "Create Camera Capture Failure!"
    rtrn = -1
  EndIf
  ProcedureReturn rtrn
EndProcedure
Define counter
For counter = 0 To 2
  Define *img = get_frame(85)
  ;Debug MemorySize(*img)
  If *img > 0
    Debug *img
    ;If CreateFile(0, "D:\file.jpg")
    ;  WriteData(0, @*img, MemorySize(@*img))
    ;  CloseFile(0)
    ;EndIf
    FreeMemory(*img)
  Else
    Debug "error:"
    Debug *img
  EndIf
NextRe: PureBasic Interface to OpenCV
Hi Phantomas,
The reason for separate memory addresses is because you're creating and releasing the web cam and query-image in the main loop.
- releasing the web cab also releases the query-image (releasing both can cause a memory fault)
Take a look at the example cv_pb_cam_database.pb (includes/pb_procedures -- Procedure: ImportImage).
- most of the web cam examples use the same format and should provide some insite
Also, there are 4 default templates to help you get started creating various type examples: binaries/default (cv_cam_default.pb, pb_cam_default.pb, etc.).
- copy a template to the "main examples" folder before using it
Let me know if you have any trouble moving forward; if so please provide additional details to what you would like to accomplish, and I will try to help.
			
			
									
									The reason for separate memory addresses is because you're creating and releasing the web cam and query-image in the main loop.
- releasing the web cab also releases the query-image (releasing both can cause a memory fault)
Take a look at the example cv_pb_cam_database.pb (includes/pb_procedures -- Procedure: ImportImage).
- most of the web cam examples use the same format and should provide some insite
Also, there are 4 default templates to help you get started creating various type examples: binaries/default (cv_cam_default.pb, pb_cam_default.pb, etc.).
- copy a template to the "main examples" folder before using it
Let me know if you have any trouble moving forward; if so please provide additional details to what you would like to accomplish, and I will try to help.
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: PureBasic Interface to OpenCV
Hello JHPJHP
Thank you for all of that. It's help me so much to access to my camera stream.
 
I need to work on image with purebasic command.
I find to save image on HD but i'd like to work in memory.
Something like that :
*image = cvQueryFrame(*capture)
CatchImage(0, *image)
I'm not good enough to understand how to do this correctly
 
If you have few minutes to help me...
In anyway, thank a lot again
			
			
									
									
						Thank you for all of that. It's help me so much to access to my camera stream.
I need to work on image with purebasic command.
I find to save image on HD but i'd like to work in memory.
Something like that :
*image = cvQueryFrame(*capture)
CatchImage(0, *image)
I'm not good enough to understand how to do this correctly
If you have few minutes to help me...
In anyway, thank a lot again
Re: PureBasic Interface to OpenCV
Hi, Stefou
If I understood your question correctly, you should take a look this http://www.purebasic.fr/english/viewtop ... 21#p433921
and next posts.
Example:
Good luck!
			
			
									
									
						If I understood your question correctly, you should take a look this http://www.purebasic.fr/english/viewtop ... 21#p433921
and next posts.
Example:
Code: Select all
IncludeFile "includes/cv_functions.pbi"
UseJPEGImageEncoder()
UseJPEGImageDecoder()
Repeat
  nCreate + 1
  *capture = cvCreateCameraCapture(0)
Until nCreate = 5 Or *capture
If *capture
  Repeat
    *image.IplImage = cvQueryFrame(*capture)
  Until *image 
  params.SAVE_INFO
  params\paramId = #CV_IMWRITE_JPEG_QUALITY
  params\paramValue = 90
  *mat.CvMat = cvEncodeImage(".jpg", *image, @params)
  Result = CatchImage(1, *mat\ptr, *mat\cols)
  *imgbuf = EncodeImage(1, #PB_ImagePlugin_JPEG);
  bufsize = MemorySize(*imgbuf)
  OpenFile(2,"c:\catched.jpg")
  For j=0 To bufsize-1
    WriteByte(2,PeekB(*imgbuf+j))
  Next
  CloseFile(2)
  cvReleaseCapture(@*capture)
EndIfRe: PureBasic Interface to OpenCV
Thank you AAT 
 
It' exactly what i wan't to do!
 
I'm happy
			
			
									
									
						It' exactly what i wan't to do!
I'm happy
Re: PureBasic Interface to OpenCV
Thanks for reply. But I should creating and releasing WebCam like this. Because I want make application which working in background, then get event* and do: open camera > make shot > store it in memory > close camera > wait next event.JHPJHP wrote:The reason for separate memory addresses is because you're creating and releasing the web cam and query-image in the main loop.
- releasing the web cab also releases the query-image (releasing both can cause a memory fault)
* Event can come randomly, for example, 3 times per hour or 10 times per 5 minutes.
I don't want keep camera "opened" (cvCreateCameraCapture()) all time while application running...
Re: PureBasic Interface to OpenCV
Hi Stefou,
I'm glad AAT was there to lend a helping hand, he was an invaluable support creating "Purebasic Interface to OpenCV".
----------------------------------------------
Hi Phantomas,
In your case working with multiple memory addresses is unavoidable, but maybe the following provides an alternative?
- create a Global image: *image.IplImage
- clone the query-image: *query.IplImage to the global image: *image.IplImage
- release the webcam (also releasing the query-image)
- work with the cloned image
			
			
									
									I'm glad AAT was there to lend a helping hand, he was an invaluable support creating "Purebasic Interface to OpenCV".
----------------------------------------------
Hi Phantomas,
In your case working with multiple memory addresses is unavoidable, but maybe the following provides an alternative?
- create a Global image: *image.IplImage
- clone the query-image: *query.IplImage to the global image: *image.IplImage
- release the webcam (also releasing the query-image)
- work with the cloned image
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: PureBasic Interface to OpenCV
It's strange, but not luck:JHPJHP wrote:In your case working with multiple memory addresses is unavoidable, but maybe the following provides an alternative?
Code: Select all
IncludeFile "includes/cv_functions.pbi"
EnableExplicit
UseJPEGImageDecoder()
UseJPEGImageEncoder()
Global *g_image.IplImage
Procedure.i get_frame(quality.i)
  Protected ret.i
  Protected *capture.CvCapture = cvCreateCameraCapture(0)
  If *capture
    Protected *image.IplImage
    *image = cvQueryFrame(*capture)
    If *image
      *g_image = cvCloneImage(*image)
      ret = 1
    Else
      Debug "Query Frame Failure!"
    EndIf
    cvReleaseCapture(@*capture)
  Else
    Debug "Create Camera Capture Failure!"
  EndIf
  ProcedureReturn ret
EndProcedure
Define counter
For counter = 0 To 2
  If get_frame(85)
    Debug *g_image
    cvReleaseImage(@*g_image)
  EndIf
NextRe: PureBasic Interface to OpenCV
Hi Phantomas,
Releasing the Global image inside a loop will force a new memory address... try the following:
- I switched cvCloneImage with cvCopy for better memory management
			
			
									
									Releasing the Global image inside a loop will force a new memory address... try the following:
- I switched cvCloneImage with cvCopy for better memory management
Code: Select all
IncludeFile "includes/cv_functions.pbi"
EnableExplicit
Global *gImage.IplImage
Procedure GetFrame(nQuality.a)
  Protected FrameWidth, FrameHeight, ReturnImage = #False
  Protected *capture.CvCapture, *image.IplImage
  
  *capture.CvCapture = cvCreateCameraCapture(0)
  
  If *capture
    If Not *gImage
      FrameWidth = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_WIDTH)
      FrameHeight = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_HEIGHT)
      *gImage = cvCreateImage(FrameWidth, FrameHeight, #IPL_DEPTH_8U, 3)
    EndIf
    *image = cvQueryFrame(*capture)
    
    If *image
      cvCopy(*image, *gImage, #Null)
      ReturnImage = #True
    Else
      Debug "Query Frame Failure!"
    EndIf
    cvReleaseCapture(@*capture)
  Else
    Debug "Create Camera Capture Failure!"
  EndIf
  ProcedureReturn ReturnImage
EndProcedure
UseJPEGImageDecoder()
UseJPEGImageEncoder()
Define nCounter
For nCounter = 0 To 2
  If GetFrame(85) : Debug *gImage : EndIf
Next
cvReleaseImage(@*gImage)If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: PureBasic Interface to OpenCV
Great! Thank you very much JHPJHP 
.
Let me one more question:
I can set custom resolution after cvCreateCameraCapture():
But this will "reopen" camera again. Can I bypass it and open camera immediately with custom resolution?
			
			
									
									
						Let me one more question:
I can set custom resolution after cvCreateCameraCapture():
Code: Select all
  cvSetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_WIDTH, 1280)
  cvSetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_HEIGHT, 720)
Re: PureBasic Interface to OpenCV
Hi Phantomas,
Using native OpenCV commands you're limited, but an alternative would be to resize the returned frame:
- this could be written multiple ways: passing the resize image to the Procedure, returning the new image, without global variables, etc.
			
			
									
									Using native OpenCV commands you're limited, but an alternative would be to resize the returned frame:
- this could be written multiple ways: passing the resize image to the Procedure, returning the new image, without global variables, etc.
Code: Select all
UseJPEGImageDecoder()
UseJPEGImageEncoder()
Define nCounter, *resize.IplImage
*resize = cvCreateImage(320, 180, #IPL_DEPTH_8U, 3)
For nCounter = 0 To 2
  If GetFrame(85)
    cvResize(*gImage, *resize, #CV_INTER_AREA)
    Debug *resize
  EndIf
Next
cvReleaseImage(@*resize)
cvReleaseImage(@*gImage)If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: PureBasic Interface to OpenCV
Updated the examples to be Unicode compliant (enabled by default).
- OpenCV_32, OpenCV_64, OpenCV_3.0
NOTE:
- most examples require user input to initiate the effect
-- a popup message will display the Description / Options when the mouse pointer is over the window
- most examples include a context menu
-- Open / Save / Exit
			
			
									
									- OpenCV_32, OpenCV_64, OpenCV_3.0
NOTE:
- most examples require user input to initiate the effect
-- a popup message will display the Description / Options when the mouse pointer is over the window
- most examples include a context menu
-- Open / Save / Exit
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Re: PureBasic Interface to OpenCV
Hi, JHPJHP,
hi, guys.
This is an example how to correct webcam's image distortions. The example is based on JHPJHP's example cv_cam_chessboard_2.pb.
You have to use binaries/images/chessboard.jpg during the calibration process.
You have to slightly move and rotate webcam along chessboard (or chessboard along webcam) during calibration.
It looks like this:
raw image

corrected image

Save code as cv_cam_undistort.pb in main folder with JHPJHP's examples.
Then you have to set "Compiler Options":

Have fun!
			
			
									
									
						hi, guys.
This is an example how to correct webcam's image distortions. The example is based on JHPJHP's example cv_cam_chessboard_2.pb.
You have to use binaries/images/chessboard.jpg during the calibration process.
You have to slightly move and rotate webcam along chessboard (or chessboard along webcam) during calibration.
It looks like this:
raw image

corrected image

Save code as cv_cam_undistort.pb in main folder with JHPJHP's examples.
Then you have to set "Compiler Options":

Code: Select all
IncludeFile "includes/cv_functions.pbi"
Global lpPrevWndFunc
#CV_WINDOW_NAME  = "PureBasic Interface to OpenCV"
#CV_WINDOW2_NAME = "Corrected image"
#CV_DESCRIPTION = "Calibrating of the webcam with 10 x 7 chessboard pattern then shows corrected image." + Chr(10) + Chr(10) +
                  "Press S key to save the pair of raw and corrected images" + Chr(10) + Chr(10) +
                  "Press Esc key to exit"
#CORNER_ROW = 6
#CORNER_COL = 9
#IMAGE_SIZE = 25
#PATTERN_SIZE = #CORNER_ROW * #CORNER_COL
#ALL_POINTS = #IMAGE_SIZE * #PATTERN_SIZE
ProcedureC WindowCallback(hWnd, Msg, wParam, lParam)
  Shared exitCV.b
  Select Msg
    Case #WM_COMMAND
      Select wParam
        Case 10
          exitCV = #True
      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
      DisplayPopupMenu(0, *param\uValue)
    Case #CV_EVENT_LBUTTONDBLCLK
  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)
  opencv = LoadImage_(GetModuleHandle_(0), @"icons/opencv.ico", #IMAGE_ICON, 35, 32, #LR_LOADFROMFILE)
  SendMessage_(hWnd, #WM_SETICON, 0, opencv)
  wStyle = GetWindowLongPtr_(hWnd, #GWL_STYLE)
  SetWindowLongPtr_(hWnd, #GWL_STYLE, wStyle & ~(#WS_MAXIMIZEBOX | #WS_MINIMIZEBOX | #WS_SIZEBOX))
  cvMoveWindow(#CV_WINDOW_NAME, 20, 20)
  ToolTip(window_handle, #CV_DESCRIPTION)  
  *param.USER_INFO = AllocateMemory(SizeOf(USER_INFO))
  *param\uValue = window_handle
  cvSetMouseCallback(*window_name, @CvMouseCallback(), *param)
  
  font.CvFont : cvInitFont(@font, #CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, #Null, 1, #CV_AA) 
  
  FrameWidth = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_WIDTH)
  FrameHeight = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_HEIGHT)
  
  Dim corners.CvPoint2D32f(#ALL_POINTS)
  Dim points(#IMAGE_SIZE)
  *source.IplImage
  *image.IplImage
  *gray.IplImage = cvCreateImage(FrameWidth, FrameHeight, #IPL_DEPTH_8U, 1)  
  
  DBL_EPSILON.d = 2.2204460492503131 * Pow(10, -16)
  While found_num < #IMAGE_SIZE
    *image = cvQueryFrame(*capture)
    If *image
      cvReleaseImage(@*source)
      *source = cvCloneImage(*image)
      cvCvtColor(*source, *gray, #CV_BGR2GRAY, 1)     
      If cvCheckChessboard(*gray, #CORNER_COL, #CORNER_ROW)
        found = cvFindChessboardCorners(*source, #CORNER_COL, #CORNER_ROW, @corners(found_num * #PATTERN_SIZE), @corner_count, #CV_CALIB_CB_ADAPTIVE_THRESH | #CV_CALIB_CB_FILTER_QUADS)
        If found
          cvFindCornerSubPix(*gray, @corners(found_num * #PATTERN_SIZE), corner_count, 3, 3, -1, -1, #CV_TERMCRIT_ITER | #CV_TERMCRIT_EPS, 20, 0.03)
          cvDrawChessboardCorners(*source, #CORNER_COL, #CORNER_ROW, @corners(found_num * #PATTERN_SIZE), corner_count, found)
          points(found_num) = corner_count
          found_num + 1
        EndIf       
      EndIf
      cvPutText(*source, "Found "+Str(found_num)+"/"+Str(#IMAGE_SIZE)+" chessboard images", 10, 30, @font, 0, 0, 255, 0)         
      cvShowImage(#CV_WINDOW_NAME, *source)
      keyPressed = cvWaitKey(100)      
    EndIf
      
    If keyPressed = 27 Or exitCV : Break : EndIf
  Wend
  If found_num = #IMAGE_SIZE
    cvPutText(*image, "The camera calibration, wait a little...", 10, 30, @font, 0, 0, 255, 0)         
    cvShowImage(#CV_WINDOW_NAME, *image)
    keyPressed = cvWaitKey(100)
    
    Dim objects.CvPoint3D32f(#ALL_POINTS)
    #CHESS_LENGTH = 24
    For i = 0 To #IMAGE_SIZE - 1
      For j = 0 To #CORNER_ROW - 1
        For k = 0 To #CORNER_COL - 1
          objects(i * #PATTERN_SIZE + j * #CORNER_COL + k)\x = j * #CHESS_LENGTH
          objects(i * #PATTERN_SIZE + j * #CORNER_COL + k)\y = k * #CHESS_LENGTH
          objects(i * #PATTERN_SIZE + j * #CORNER_COL + k)\z = 0.0
        Next
      Next
    Next
    object_points.CvMat
    image_points.CvMat
    point_counts.CvMat
    cvInitMatHeader(@object_points, #ALL_POINTS, 3, CV_MAKETYPE(#CV_32F, 1), @objects(), #CV_AUTOSTEP)
    cvInitMatHeader(@image_points, #ALL_POINTS, 2, CV_MAKETYPE(#CV_32F, 1), @corners(), #CV_AUTOSTEP)
    cvInitMatHeader(@point_counts, #IMAGE_SIZE, 1, CV_MAKETYPE(#CV_32S, 1), @points(), #CV_AUTOSTEP)
    *camera_matrix.CvMat = cvCreateMat(3, 3, CV_MAKETYPE(#CV_32F, 1))
    *distortion_coeffs.CvMat = cvCreateMat(4, 1, CV_MAKETYPE(#CV_32F, 1))  
    cvCalibrateCamera2(@object_points, @image_points, @point_counts, FrameWidth, FrameHeight, *camera_matrix, *distortion_coeffs, #Null, #Null, 0, #CV_TERMCRIT_ITER | #CV_TERMCRIT_EPS, 50, DBL_EPSILON)             
    
    *mapx.IplImage = cvCreateImage(FrameWidth, FrameHeight, #IPL_DEPTH_32F, 1) 
    *mapy.IplImage = cvCreateImage(FrameWidth, FrameHeight, #IPL_DEPTH_32F, 1)    
    cvInitUndistortMap(*camera_matrix, *distortion_coeffs, *mapx, *mapy)
    
    cvNamedWindow(#CV_WINDOW2_NAME, #CV_WINDOW_AUTOSIZE)    
    cvMoveWindow(#CV_WINDOW2_NAME, *image\width+30, 20)
    Repeat
      *image = cvQueryFrame(*capture)    
      If *image       
        cvReleaseImage(@*imgundist)         
        *imgundist = cvCloneImage(*image)    
        cvUndistort2(*image, *imgundist, *camera_matrix, *distortion_coeffs, #Null)         
        cvShowImage(#CV_WINDOW_NAME, *image)
        cvShowImage(#CV_WINDOW2_NAME, *imgundist)   
      EndIf
      keyPressed = cvWaitKey(10)    
      
      If keyPressed = 83 Or keyPressed = 115
        If FileSize("ImagePairs") <> -2 : CreateDirectory("ImagePairs") : EndIf
        cvSaveImage("./ImagePairs/"+FormatDate("%yyyy-%mm-%dd %hh-%ii-%ss", Date()) + ".jpg" , *image, #Null)
        cvSaveImage("./ImagePairs/"+FormatDate("%yyyy-%mm-%dd %hh-%ii-%ss", Date()) + "_Undistorted.jpg", *imgundist, #Null)
        Debug "Saved"
      EndIf      
      
    Until keyPressed = 27 Or exitCV
    cvReleaseMat(@*distortion_coeffs)
    cvReleaseMat(@*camera_matrix)
  EndIf
  FreeMemory(*param)
  cvReleaseImage(@*gray)
  cvReleaseImage(@*source)
  cvReleaseImage(@*mapx)
  cvReleaseImage(@*mapy)    
  cvDestroyAllWindows()
  cvReleaseCapture(@*capture)
Else
  MessageBox_(0, "Unable to connect to a webcam - operation cancelled.", #CV_WINDOW_NAME, #MB_ICONERROR)
EndIf

