ginput() in opencv-python

The Image Processing Toolbox in MATLAB has this very useful utility called as ginput, which allows manually picking co-ordinate points from an image. I tried to recreate that functionality in python based OpenCV, and the result is the following code:


import cv2
import numpy as np
from matplotlib import pyplot as plt
import os

a = np.array([0,0], dtype='float32')
def getXY(imgPath):

 try:
   os.environ["DEBUG"]
   DEBUG = 1

 print "-------------------------------"
 print "Using OpenCV version : ",cv2.__version__
 print "-------------------------------"

 print "TASK : Mimic getxy() feature of MATLAB"
 print "***************************************"

 except KeyError:
    #print "For verbose mode, set DEBUG flag"
    DEBUG = 0

 #define the event
 def getxy(event, x, y, flags, param):
   global a
   if event == cv2.EVENT_LBUTTONDOWN :
      a = np.vstack([a, np.hstack([x,y])])
      if (DEBUG):
      print "(row, col) = ", (x,y)

   #Read the image
   img = cv2.imread(imgPath)
   if (DEBUG):
      print "Reading the image..."

   #Set mouse CallBack event
   cv2.namedWindow('image')
   cv2.setMouseCallback('image', getxy)
   if (DEBUG):
      print "Set MouseCallback functionality..."

   #show the image
   print "Click to select a point OR press ANY KEY to continue..."
   cv2.imshow('image', img)
   cv2.waitKey(0)
   cv2.destroyAllWindows()

   #obtain the matrix of the selected points
   b = a[1:,:]
   if (DEBUG):
      print ""
      print "The clicked points..."
      print b, b.dtype, b.shape

   print "The selected points are returned as a float64 MATRIX..."
   return b

Steps to use it :

  • save the above source code as getXY.py in your working directory.
  • In your python code, import this file, i.e.,

from getXY import *

  • Pass the image path to getXY, and start clicking on the displayed image. The no. of times you click, those many points will get saved.
  • If you want a verbose version, set the environment variable DEBUG = 1 from the terminal before running the code, i.e.,

DEBUG=1; export $DEBUG

That’s it! I’ll upload the code onto a git repo as well soon and provide a link here as well.

  • To remove the verbose code, unset the DEBUG variable, i.e, :

unset $DEBUG

Advertisements

MATLAB: Using ANN library wrapper in Windows XP

ANN (Approximate Nearest Neighbours) is an extremely useful library when working with any type of application where the properties of data points are influenced by their neighbours. The MATLAB MEX-wrapper for the same provided by Shai Bagon, along with the patches, compiles effortlessly in Linux (have tried on F16 and F17). However, making the same work in Windows turned out to be quite an effort. First, the MATLAB inbuilt compiler for Windows (lcc) continuously kept crashing whenever I tried executing the library, and second, the lack of pre-existing solid C/C++ compiler made things difficult.

After searching on the net for free and supported compilers for MATLAB R2010a, I first tried Open Watcom, but it gave too many errors during compilation of the mex-wrappers.  Then it was the turn to check out MS Visual C++ Express Edition. Tried on a friend’s system having MS-VC++ 2010, and it too gave quite a few errors during compilation. Thought to try out MS-VC++ 2008, and guess what, it worked out of the box and the mex-wrapper compiled with quite an ease 🙂 . Wonder why MS-VC++ 2010 created issues..

MATLAB: Run m-file From Linux Terminal / DOS

Yes, MATLAB m-files can very much be executed without initiating the MATLAB GUI. This can be quite handy when when running multiple codes simultaneously without creating a huge clutter for the user, or when running multiple instances of MATLAB and there is a need to prevent unnecessary eating up of the RAM through its GUI.

In Linux, it works via the re-direction operator ( < ), while in Windows, it has to be done using the -r flag. The steps are detailed below:

For MATLAB installations on Linux, ensure the MATLAB soft link is available in /usr/local/bin, so that it can be called from the terminal without specifying its full installation path, i.e.,

cd /usr/local/bin

sudo ln -s /path_to_MATLAB_installation/matlab

cd

matlab -desktop

Once MATLAB link has been created, exit the MATLAB GUI. Now run your m-file (say: test_run.m) from the terminal as:

matlab -nodesktop -nosplash < /path_to_file_location/test_run -logfile test_run.log

Thats it! The “-nodesktop” option ensures the full GUI isnt initiated and only the MATLAB command prompt pops up, “-nosplash” prevents the MATLAB splash screen from showing up. The redirection operator will run all the commands in the m-file as they would in a normal way and “-logfile” logs all that shows up in the MATLAB command window.

In Windows, the slight modification is that we have to first cd to the location where the m-file is present

cd path_to_file_location\

matlab.exe -nodesktop -nosplash -r test_run -logfile test_run.log

And we are done!

P.S : 1) Dont forget to check out the difference in RAM usage with “-nodesktop” enabled and normal GUI way

2) DO NOT put .m with the file name when using this command, else it’ll result in an error!

MATLAB : Generate variable name and allot vector / matrix to it

Matlab provides a nice and simple way to generate continuous set of variable names, say in the form of var1, var2,… etc. This can be accomplished using genvarname and eval commands. Here i’ll show an example where we need to store columns of a matrix A in 3 vectors var1, var2 and var3. Following is the code snippet :

n = 3;                                         % say

A = [1 2 3;4 5 6;7 8 9];            %say

for i = 1:n

val = genvarname([‘var’ num2str(i)]);

eval([val ‘=A(:,i);’]);

end

And you are done.. the columns of A get stored in the vectors var1, var2 and var3. Similarly, even block matrices within A can be assigned this way. This is a much more elegant and faster way than doing the same thing via for-loops.