Getting infinities with numpy.exp()

Posted on Sat 24 May 2014 in bugs • Tagged with numpy, pythonLeave a comment

So I spent quite a lot of time this week trying to find out why I was getting infinities in one of my codes I'm working on.

In the code I have a big numpy.ndarray, let's call it a, which I then pass into numpy.exp() and save into another numpy.ndarray, let's call it b. Everything was working fine until I started detecting NaN-s somewhere later in the code. I traced the problem back to this b = numpy.exp(a) step; it turned out b contained inf at some places. More precisely, b was inf where a was around 90 or above.

So I ran python and typed:

a = 90

b = np.exp(a)

b 1.2204032943178408e+39

np.isinf(b)

False

OK, this is big, but it's not inf, right? Let's try bigger.

a = 120

b = np.exp(a)

b 1.3041808783936323e+52

np.isinf(b)

False

Still not inf. But hey, what type is b actually?

type(b)

< type 'numpy.float64' >

Everything was clear now. Throughout my code I was using numpy.float32 as the dtype of my arrays and that was the source of the problem.

Check this out:

a = np.finfo(np.float32).max

b = np.finfo(np.float32).max * 10

c = np.zeros(2, dtype = 'float32')

c[0] = a

c[1] = b

c

array([ 3.40282347e+38, inf], dtype=float32)

np.isinf(a) False

np.isinf(b) False

np.isinf(c[0]) False

np.isinf(c[1]) True

Why is b not inf and c[1] is?

Because:

type(b)

< type 'numpy.float64' >

type(c[1])

< type 'numpy.float32' >`

Point of story? Be careful what types you're using to store your data, stupid!


Line camera

Posted on Fri 02 May 2014 in fun • Tagged with c++, opencv, videoLeave a comment

I wrote this one a while ago, it's a line camera! Check the video for a better explanation.

Look!!

How does it work?

Well, it just takes the center vertical line of the input video (which can be either a video file, or a video straight from the camera) and appends it as a last vertical line in a new image. Simple but you can get nice outputs. Yay!

Show me the code!

The code was written in c++ and it uses OpenCV.

linescan.cpp download
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
 
int main (int argc, char* argv[])
{
  if (argc < 3) {
    cout << "Something's wrong with the provided parameters..." << endl << endl;
    cout << "Usage: ./lineScan   streamType streamLocation" << endl << endl;
    cout << "streamType - 0 = file, 1 = camera" << endl;
    cout << "streamLocation - path to the video stream" << endl;
 
    return 0;
  }
  
  int streamType = atoi(argv[1]);
  string videoStreamLocation = argv[2];
     
  VideoCapture vcap;
  Mat image;
  
  if (streamType == 0) { 
    if(!vcap.open(videoStreamLocation)) {
      cout << "Error opening video stream" << endl;
 
      return 0;
    }
  }
  else {
    if(!vcap.open(atoi(argv[2]))) {
      cout << "Error opening video stream" << endl;
 
      return 0;
    }   
     
    vcap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    vcap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
  }
 
  namedWindow ("line", CV_WINDOW_AUTOSIZE);
     
  long frame = 0;
 
  Mat lineImage = Mat::zeros(Size(640, 480), CV_8UC3);
  Mat combinedImage = Mat::zeros(Size(1280, 480), CV_8UC3);
    
  while(true) {
    if(!vcap.read(image)) {
      cout << "No frame" << std::endl;
      return 0;
    }
     
    if (streamType == 0) {
      Mat imageScaled(Size(640, 480), image.type());
     
      resize(image, image, imageScaled.size());
    }
   
    line(image, Point(image.cols / 2 + 1, 0),
                Point(image.cols / 2 + 1, image.rows - 1),
                Scalar(255, 0, 128));
 
    if (frame >= lineImage.cols) {
      lineImage.colRange(1, lineImage.cols - 1).copyTo(lineImage.colRange(0, lineImage.cols - 2));
      image.col(image.cols / 2).copyTo(lineImage.col(lineImage.cols - 2));
    }
    else {
      image.col(image.cols / 2).copyTo(lineImage.col(frame));
    }
     
    image.colRange(0, image.cols - 1).copyTo(combinedImage.colRange(0, image.cols - 1));
    lineImage.colRange(0, image.cols - 1).copyTo(combinedImage.colRange(image.cols, combinedImage.cols - 1));
   
    imshow("line", combinedImage);
     
    frame ++;
     
    stringstream ss;
 
    ss.fill('0');
    ss.width(4);
 
    ss << frame << ".jpg";
     
    /*imwrite(ss.str().c_str(), combinedImage);*/
         
    if(waitKey(1) >= 0) waitKey(0);
  }  
}

I'll also include the contents of the CMakeLists.txt file, just save this as CMakeLists.txt in the same folder:

CMakeLists.txt download
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

project (LineScan)

find_package (OpenCV REQUIRED)

add_executable(lineScan linescan.cpp)
target_link_libraries (lineScan ${OpenCV_LIBS})

The code is also available on github.

How to compile?

Assuming that you have OpenCV and cmake installed and that you have the linescan.cpp and CMakeLists.txt files in a folder, then you could do something like:

mkdir build cd build cmake .. make

How to run it?

After compiling, just go into the build folder and run the code using:

./lineScan

This will give tell you which parameters the program expects.

How to make your own video?

Uncomment the imwrite line in the source, recompile and run the code. This will save each frame into a .jpg image. To convert the generated sequence of images into a video, you could use something like:

ffmpeg -f image2 -i tmp/%04d.jpg -b 800k video.mpg

That's it! Have fun!


I got an idea the other day

Posted on Thu 01 May 2014 in funLeave a comment

It was one of those great ideas, of course.

Yes, I should!

This will (hopefully) be a place where I will share some of the small (and for some people fun) projects that I worked on in my free time.

If there's source code that goes with the project, I'll try to make it available.

It could also happen that I post some scripts that I wrote or found somewhere online, which I often use and even more often lose.

And so it begins! Yay!