kansairobot
Several Methods for doing things

Mar
24

Well, the premise is very simple. You have a folder full of image files and you want to read those files without having to specify one by one in your code. This is standard in other computer vision libraries so how to do it in OpenCV?

The documentation in OpenCV says that you can use videoCapture with some notation for varying names of the file (such as %02d) but this method fails (and the code in examples fail too) when  not the simplest of names.

So how to do it. Here we present a code using the function glob

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <iostream>

using namespace cv;
using namespace std;

int main()
{

vector<String> images; // notice here that we are using the Opencv’s embedded “String” class
String patern = “D:\\Path\\to\\files\\”; // again we are using the Opencv’s embedded “String” class
glob(patern, images);

for(int i=0;i<images.size();i++)
{
Mat img = imread(images[i]);

if(!img.data) cout<<“Cant open”<<images[i]<<endl;
else
imshow(“Image”,img);

if(waitKey(0)==’q’) break;

}

return 0;

And that is it! simple as it should be🙂

Feb
04

Well, after I published yesterday method on filling holes, I found out that my method had some cases in which it didn’t work. For example when point (0,0) was surrounded completely by a white area.

So, I was taught another method (thanks Michael Burdinov!) to do the same, and I post it here.

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{

char* filename = argc >= 2 ? argv[1] : (char*)”region3.jpg”;
Mat img = imread(filename, 1);
namedWindow(“Image”);
imshow(“Image”, img);

Mat thresh;
Mat gray;

cvtColor(img,gray,COLOR_BGR2GRAY);
//threshold(gray,thresh,0,255,THRESH_BINARY_INV+THRESH_OTSU);
threshold(gray,thresh,0,255,THRESH_BINARY+THRESH_OTSU);

imshow(“thresh”,thresh);

Mat bwImage=thresh.clone();

vector<vector<Point>> contours;

findContours(bwImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
drawContours(bwImage, contours, -1, Scalar(255), CV_FILLED);

imshow(“contours”,bwImage);
while(char(waitKey(1)) != ‘q’) {}
return 0;
}

It makes use of the capability of OpenCV to find contours and fill them. Very elegant and simple way of doing what I was looking for. Hope it helps to any of you looking to do the same.

Feb
03

Well, it has been long since I posted here.
Currently I am working with OpenCV, doing several kinds of stuff.

Since some time ago I have been working on computer vision (not necessarily with OpenCV, I also tried Halcon) and one of the little things that bugged me was how to fill the holes of regions such as the following:

regionabierta

I’ve tried to “closing” it (with the close functions or equivalent) but to no avail, adjacent regions get connected as a bad side effect. I couldn’t fancy a neat way to do it.

Until I came up with this code

 

int main( int argc, char** argv )
{
char* filename = argc >= 2 ? argv[1] : (char*)”regionabierta.jpg”;

Mat img = imread(filename, 1);
namedWindow(“Image”);
imshow(“Image”, img);

Mat thresh;
Mat gray;

cvtColor(img,gray,COLOR_BGR2GRAY);
threshold(gray,thresh,0,255,THRESH_BINARY_INV+THRESH_OTSU);

imshow(“thresh”,thresh);

Mat edgesNeg=thresh.clone();
floodFill(edgesNeg,Point(0,0),CV_RGB(0,0,0));
imshow(“uno”,edgesNeg);

Mat relleno;
relleno=(edgesNeg|gray);
imshow(“relleno”,relleno);

while(char(waitKey(1)) != ‘q’) {}
return 0;
}

I also have an alternative way of doing this

int main( int argc, char** argv )
{
char* filename = argc >= 2 ? argv[1] : (char*)”regionabierta.jpg”;

Mat img = imread(filename, 1);
namedWindow(“Image”);
imshow(“Image”, img);

Mat thresh;
Mat gray;

cvtColor(img,gray,COLOR_BGR2GRAY);
threshold(gray,thresh,0,255,THRESH_BINARY+THRESH_OTSU);

imshow(“thresh”,thresh);

Mat edgesNeg=thresh.clone();
floodFill(edgesNeg,Point(0,0),CV_RGB(255,255,255));
imshow(“uno”,edgesNeg);

bitwise_not(edgesNeg,edgesNeg);

Mat relleno;
relleno=(edgesNeg|thresh);
imshow(“relleno”,relleno);

while(char(waitKey(1)) != ‘q’) {}
return 0;
}

It is similar. Both result in the following:
relleno

As you can see the holes have been filled. Hope this helps to any of you

Apr
05

Well, it has been long overdue but finally I am posting how to build a DLL in C++ using Visual C++ 2010 Express.

1. Creating the Project

First you start normally with File->New -> Project

When the window appears select Win32 Console Application, put a name to your DLL (say MyDLL) and click Next.

You will get a “Welcome” window, so just click Next

And then you will get a Application Settings window. Over there click DLL and “Empty Project”

DLL1

You are almost finished with this so click Finish. This will create the framework of your project.

2. Writing your code

The next step is to write your code. In this case we are creating just one function called MyFunction which is going to take one int parameter and return the parameter plus one. (Simple but that is the point!)

Go to Header Files in the left panel(Solution Explorer) and right click Add ->New Item

You will get a window where you will select Header File (.h) from the Code section.

DLL2

Name your file (in our case we will name it myfuncion.h) and Add it. Go to Source Files in the Solution Explorer and do the same this time for a C++ file (.cpp)

Now write the necessary code for the header and the source:

namespace first
{
class myFirst
{
public:
static int MyFunction(int a);
};
}

and

#include “myfuncion.h”

namespace first
{
int myFirst::MyFunction(int a)
{
return(a+1);
}
}

3. Let the world know about your function (Export!)

Now you have to make a way to let the world know about this function MyFunction. To do this , similar to the previous step add a new Item to your Resource Files. You can use any type of file (like .h) but be sure to name it as a def file. In our case we named it MyDLL.def 

This file is a text file that contains the export functions of the DLL. In our case

LIBRARY MYDLL
EXPORTS
MyFunction @1

Unfortunately this is not enough. You have to link your project with this file so go to Project-> Properties (or ALT F7) and in the window select Configuration Properties-> Linker-> Input

Then in the right panel select Module Definition File and write the name of your def file: MyDLL.def

Click Apply and OK.

Now it is time to build your DLL. Click Debug-> Build Solution and then you are done and ready to use your DLL!

 

Feb
20

In my previous post I wrote about how to make a simple graphical program with C++ and CLR. In this post I will write about how to make a (graphical) program that uses functions included in a DLL. This program can be written in C++ or VB (or any other language). In this post I will be talking about a C++ program.

I know I should have started by building the DLL but we will see that in a future post later. In this post, I will suppose we have already the DLL and we need to use it from a program we are building in C++

So…

How to build a program in C++ using a simple window interface that uses functions from a DLL?

First.

Open Microsoft Visual C++ and build a Windows Form Application project with the necessary widgets. You can see how to do this in the previous post

We now have a file called Form1.h in which first we have to put the following line

include <windows.h>

You have to be careful where you put your statements. Put this include declaration in the first line after the #pragma directive.

Now let’s say you want to use a function from a DLL that has the following form:

int MyFunction(char*,int);

Second

Put a typedef declaration to make things easier: In this case:

typedef int (__stdcall * pFunc)(char *, int);

(declare a typedef for any kind of function that you want to call. Functions with the same structure need only one typedef)

Third
Next we will declare some variables as private member variables of  the Form1 class. Be careful and write them after the region that is automatically generated (Don’t change that part by mistake!). Usually this is marked by a

#pragma endregion

statement.

So we declare a variable to hold the handle to the DLL and a pointer for each function you wish to call as in:

HINSTANCE hGetDLL;

FARPROC pMyFunction;

Then we declare a variable of the type we defined previously as in

pFunc myFunct;

Fourth
From now on do the following inside the Form1_Load function (which is the function that gets called when the Form loads) (in case you can’t find this function in your code, you can generate it easily by just going to the design window and double clicking the Form1 form. You will get then the function private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)   )

Get a handle to the dll:

 /* get handle to dll */
hGetDLL = LoadLibrary(LC:\\MyDLL.dll”);

Notice the L we put in the beginning. Not using it will generate an error!

Then get a pointer to each function:

pMyFunction=GetProcAddress(HMODULE (hGetDLL),“MyFunction”);

and now get the function:

myFunct=pFunc(pMyFunction);

Fifth

Now you are ready to use the function myFunct from anywhere inside the functions of the Form! Enjoy!

Oh! one more thing! Don’t forget to release the dll in the last part of your program (wherever that could be) with:

/* Release the Dll */
FreeLibrary(hGetDLL);

Feb
17

In this post I will write about creating a SIMPLE windows application using C++ and CLR. I have found that if you search for something like this on the internet you find a lot of complicated examples and explanations but not something simple which many of us require. So this post is to fill this need.

First Open MS visual C++ and click on File-> New-> Project
You will find yourself with a window like the following:

create window for CLR

So select Windows Form Application from the CLR project type, put a name to your project and click OK. This will create the project in the folder you designated.

Once you have created your project you will have a blank window (a “Form”)  in which you can put any widget you want. Since this is a simple application we will just put two Textboxes widgets and a button. Our application will transfer the value plus one of one of these textboxes into the other once we press the button. Simple enough!

So we start by going with the cursor to the right side of the VC++ window and find the “Toolbox”. You don’t need to click, just put the mouse over and it will open. (An alternative is View-> ToolBox).

From the toolbox find “Common Controls” and then “TextBox”. Drag one into your main form. Do this again for the other testbox or simply copy and paste the first one. Then do the same for a button (also to be found under “Common Controls”)

Now you will have two textboxes and a button. Select the button (don’t double click it yet) and go the properties window (situated also on the right or select View->Other windows->properties window.

Find the Text property and write Transfer 

In this properties window you can also change (and it is a good idea but we are not doing it here yet) the Name of the widget. This is useful when you are referring to these widgets in your code.

In the same way you can change the default text in your textboxes and the the text in your main form. Right now we are just not doing it.

So now you have something like this:

Save your project and now double-click your “transfer” button.

Once you do this you will open the “code” part of the form.  There is a lot of code inside that you should not modify! because it is the code that generates all the graphical widgets you just designed.

However the point in which you have the cursor now is safe, and it is the place in which you are going to put the functionality of the button.

So now you are inside the click function of your button. Write the following so that you finish with the following function:

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
int a;

a=System::Int32::Parse(textBox1->Text);
a++;
textBox2->Text=a.ToString();
}

So what are we doing here?

First declaring an integer variable a. Now how on earth we get the value as an integer from the text of the textbox? That is something so simple and yet so hard to find in the net. You just simply use System::Int32::Parse for the text property of the textbox.

Then you increment the variable and do the opposite. Assign the value converted to a string with .ToString() for the variable to the text of the second textbox.

Save and and press F5 to build and start and after the corresponding compilation and linking voila! you will have your application running!

Try it and enjoy it!

Jan
24

Haven’t you have sometimes the following situation: You have some data in a Excel Sheet (Say, Day1 Price1, Day 2 Price 2, etc) and you make a graph of it. Quite simple. Now you got another idea. You want to mark SOME of the data as “interesting”. An example? see next figure:

An excel chart with interesting values marked

How do you do that?

Well here is an easy method:

  1. First you make two colums with your data. In this case I put Columns A and B with dates and prices.
  2. Next you go to another sheet (in my case Sheet2) and make a column with the dates that you find interesting. Later you can make this sheet invisible if you want (*)
  3. Then you put two more columns in the first sheet: One for interesting dates and one for interesting values.

In the “interesting dates” column (specifically in the C2 cell) you put the following formula:

=VLOOKUP(A2,Sheet2!$A$2:$B$20,1,FALSE)

and then on the “interesting values” column (specifically in the D2 Cell) you put

=IF(C2>0,B2,#N/A)

which gives you a lot of #N/A values except in the interesting values you want to graph.

and then just graph the “interesting values” as well. You can edit the markers so that they will be circles of the color you prefer (like in our case) and eliminate the lines.

An example excel workbook is here, you can check it out:

howtomarkinterestingvalues

Hope this has been helpful to you as it was to me🙂

(*) To make a sheet invisible go to the Format Menu (I am sorry I am not sure if that is the way it is named since my excel is in japanese(書式)) and to the sheet option. There is the Hide and the Unhide commands.

Mar
24

After much twitching and trying several examples I could do the vector field I was looking for. It looks like this:

vector field (2 arrays)

Two arrays of vectors around a circle

In the image we can see two arrays of 3D vectors around a circle. Also two sliders that can rotate the 3D axis so as to be able to see the 3D vectors better.

Points to be taken:

As far as I know there is no forum to obtain help when using this tool. Also the pdf manual does not document some functions that you can find int he HTML manual. So as a way of helping I am posting here the code to generate this plot.

Also take attention to the function vecopt. This function disables automatic scaling in vector fields which is the default option!!! I am not really sure why they put automatic as the default as it caused me troubles but well fortunatelly I could disable it

Anyway, here it is the code:

#include "stdafx.h"
#include
#include
#include "dislin.h"

#define NUMPOINTS 40

#define ROT1 184.0f
#define ROT2 0.0f

static int id_draw, id_but, id_lab1, id_lab2, id_scl1, id_scl2;
static float xrot1 = ROT1, xrot2 = ROT2;

float bxp[NUMPOINTS],byp[NUMPOINTS],bzp[NUMPOINTS];
float bxv[NUMPOINTS],byv[NUMPOINTS],bzv[NUMPOINTS];

float range;
void myplot (int id);

int _tmain(int argc, _TCHAR* argv[])
{
int i;
int ip, ip1, ip2;

double fpi=3.141592653;

range=100.0; //used to be one
double radius=80.0; //radius of the pedal

// Preparing the data

float angle=0; // the angle of rotation
float anglestep=((2*fpi)/NUMPOINTS); //the rotation step at which we graph the vectors

for(i=0,angle=0; i<NUMPOINTS;i++,angle+=anglestep)
{
bxp[i]=radius*sin(angle);
byp[i]=0.0;//-100.0;
bzp[i]=radius*cos(angle);
printf("%f %f %f \n",bxp[i],byp[i],bzp[i]);
bxv[i]=40.0*sin(2*angle);
byv[i]=0.0;
bzv[i]=0.0;//40.0;//*sin(angle/2);//0.0;

}

swgtit ("DISLIN 3D Vector Field"); // Defines a title displayed in the main widget
ip = wgini ("hori"); // Initializes the widget routine and creates main widget
swgwth (-50); //sets default width of horizontal and parent base widgets
ip1 = wgbas (ip, "vert"); // creates a container widget
swgwth (-15);
ip2 = wgbas (ip, "vert"); // creates a container widget

// swgdrw(0.4);
swgdrw ((float) (2100./2970.)); //modifies the height of draw widgets
// the default here which is height=width (a square draw widget)
id_lab2 = wglab (ip1, "3D Vector Field:"); //creates a LABEL widget
id_draw = wgdraw (ip1); // creates a DRAW widget for PLOTTING

swgopt ("track", "scroll"); //set widgets options

// changes the behavior of callback routines
// for track the callback routine is called for every change

id_lab1 = wglab (ip2, "Azimuthal Rotation Angle:"); //LABEL
id_scl1 = wgscl (ip2, " ", 0.f, 360.f, ROT1, -1); //creates a SCALE widget
id_lab1 = wglab (ip2, "Polar Rotation Angle:"); //LABEL
id_scl2 = wgscl (ip2, " ", -90.f, 90.f, ROT2, -1); // SCALE
swgcbk (id_scl1, myplot); // connects a widget with a callback routine
swgcbk (id_scl2, myplot);

myplot (id_scl1);
wgfin (); //terminates the widgets routines

return 0;
}

void myplot (int id)
{
if (id == id_scl1)
xrot1 = gwgscl (id); //returns the value of a scale widget
else if (id == id_scl2)
xrot2 = gwgscl (id);

scrmod ("revers"); //background white
setxid (id_draw, "widget"); //defines an external graphic windows (all graph output is sent
//there id_draw is the widget id)
metafl ("xwin"); //defines the metafile format
disini (); //initiates dislin
erase(); //erases the plot
hwfont (); //sets a font

name ("X-axis", "x"); //defines axis titles
name ("Y-axis", "y");
name ("Z-axis", "z");
labdig (-1, "xyz"); //sets the number of digits after decimal point(-1: integer)

// center();
// axspos (400, 2300); //determines the position of an axis system
axspos(800,2000);
axslen (1800, 1800); //determines the size of an axis system

view3d (xrot1, xrot2, 6.0f, "angle"); //defines the VIEWPOINT!
height (50); //defines the character height

graf3d (-range, range, -range, 0.2*range, -range, range, -range, 0.2*range, -range, range, -range, 0.2*range);
box3d (); //plots a border around the 3Dbox

// vecclr (-2); // defines the colors of the arrows heads

vecopt(1,"scale");

color("red");
vectr3(0.,-100.0,0.,20.0,-100.0,0,-2);

//vecclr(254);
vecf3d(bxv,byv,bzv,bxp,byp,bzp,NUMPOINTS,-1);

color("blue");
vecf3d(byv,bxv,bzv,bxp,byp,bzp,NUMPOINTS,-1);

disfin (); //ends dislin
}

As you can see the code is heavily commented so that anyone can understand what is happening.

There are still some issues I want to address (add mouse capability, and some issues with the height of the draw widget but I think it is going well so far)

Mar
18

I finally found a tool that could give me what I want: a 3D vector field. The name of this tool is DISLIN and it was developed by Helmut Michels from the Max Planck Institute in Germany.

So far I have installed the C version (apparently there is no C++ version!) and I saw that there is a Java version as well. (and Fortran!- well, they are scientiests!). After setting the necessary environmental parameters and PATH I finally could have my first graphs:

2D and 3D vector fields

They look quite satisfactoy and of course I still have to twicht a little bit my way to do what I want them to do, but that is work from now on…

I leave with just a paragraph from the installation instructions: 

“Microsoft Visual C++ 2008 Express Edition can generate native and managed code. If you want to generate native code, you can use the following instructions:

  • Download and install the DISLIN distribution for MS Visual C++ (dl_10_vc.zip). Define the environment variable DISLIN and modify the PATH variable as described in the DISLIN README file.
  • Create a new Win32 project for a Win32 Console Application in MS Visual Studio.
  • Go to Project -> Properties -> Configuration Properties -> C/C++ -> General and add the DISLIN directory (i.e. c:\dislin) to the field Additional Include Directories for finding the DISLIN header file dislin.h.
  • Add the library disvcm.lib with the full path to the linker properties: Project -> Properties -> Configuration Properties -> Linker -> Input
  • Set the runtime library to multi-threaded: Project -> Properties -> Configuration Properties -> C/C++ -> Code Generation -> Runtime Library -> Multi-threaded (/MT)

If you want to use DISLIN from the command line, you can compile and link your program for example with the command:

cl /Ic:\dislin exa_c.c c:\dislin\disvcm.lib user32.lib gdi32.lib

The instructions for generating managed code are:

  • Download and install the DISLIN dotnet distribution dl_10_cs.zip. Define the environment variable DISLIN and modify the PATH variable as described in the DISLIN README file.
  • Create a new project for CLR Console Application in MS Visual Studio.
  • Go to Project -> Properties -> Configuration Properties -> C/C++ -> General and add the DISLIN directory (i.e. c:\dislin) to the field Resolve #using References.
  • Add the DISLIN reference disnet.dll with the full path to the common properties: Project -> Properties -> Common Properties -> Add New Reference

If you want to use DISLIN from the command line for generating managed code, you can do it for example with:

cd c:\dislin\examples\cpp
copy c:\dislin\disnet.dll
cpp /clr curve.cpp “

Mar
18