(kmatzen)So, it seems that I paid an idiot tax by buying this book. Some code is just outright wrong. One example is that the book states cvSize is defined as:
CvSize cvSize (int height, int width);
but in reality, it is defined as
CvSize cvSize (int width, int height);
If I find any more mistakes like this, I will post them on the FAQ.
So the first question you have to ask yourself is why are you deleting the vector if it is on the stack. Yes, the vector is dynamically allocating memory on the inside for its own use. However, its destructor will take care of deleting that memory. When the activation context is complete, the vector's scope will be destroy, the vector's desctructor will be called, and the memory will be freed. This is a different story if you allocated a vector with the new operator. Then you have to delete that memory eventually since it has a global scope.
So this is definitely a bug and you WANT it to seg fault. However, guarantees regarding seg faults are not provided. Make sure you carefully understand scoping, dynamic versus static allocation, and maybe a bit of RAII (resources allocation is initialization.)
There are two sets of issues here. The first is that certain files must be present in your home directory. I don't have the knowledge how to deploy these files to home directories so they are on the projects site. id_rsa and QtCreator.ini are provided.
Secondly, for whatever reason, after installing Qt Creator, it no longer appears in the Applications menu. I have set things up so that you can type 'qtcreator' in the terminal to launch the IDE.
(kmatzen) No, in my haste, my code was a bit sloppy, but the functionality remains intact. The camera driver is set to automatically capture frames and allow them to be processed later. During saving, I stop servicing the frame queue and after awhile it fills up and frames begin dropping (you still see them on the screen, you just wouldn't be able to process them if you wanted.) A better design would have a separate thread performing filtering and saving.
No, this is incorrect. mad in this case is specific to the Maemo platform and is not the mad found in Ubuntu's repositories. Use either a lab machine or the virtual disk image provided as custom installations are no longer supported by the course staff.
The error message you refer to looks something like this:
cs4670@cs4670:~/Desktop/project1$ scp cs4670 root@192.168.2.15:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
30:1c:9f:df:a3:51:52:b4:83:f3:f7:b5:3b:50:d1:00.
Please contact your system administrator.
Add correct host key in /home/cs4670/.ssh/known_hosts to get rid of this message.
Offending key in /home/cs4670/.ssh/known_hosts:1
RSA host key for 192.168.2.15 has changed and you have requested strict checking.
Host key verification failed.
lost connection
Every N900 we have uses the same IP address over usb0 and the same public-private key pair. However, each has a different MAC address. If this were to happen on the internet, you would want to be informed that the server may be masquerading. However, in our case, we know that things are safe.
The fix is to delete ~/.ssh/known_hosts
This is true. The GUI framework that is being used does not release memory before the program terminates. Why is this the case? The framework uses this memory throughout the execution of the program and deleting it right before the program terminates doesn't really provide much benefit. (Imagine sweeping up your house before burning it to the ground.) Therefore your valgrind output will be cluttered with these leaks. I recommend always cleaning things up anyway in case someone were to reuse your code in their project. Some people don't provide this courtesy.
You can easily find where YOUR code is leaking with the following method.
valgrind --leak-check=full ./cs4670 -f your -i parameters -o and such 2> dump
grep dump -e Project1.cpp
Note the 2> dump at the end of the valgrind command. This simply pipes stderr from valgrind to a file named dump. The grep command searches for instances that arose from your code in Project1.cpp. If it prints nothing, then you don't have memory issues. If it prints some lines, example the relevant line numbers.
void cvSplit (IplImage * src, IplImage * dst1, IplImage * dst2, IplImage * dst3, IplImage * dst4);
void cvSplit (IplImage * src1, IplImage * src2, IplImage * src3, IplImage * src4, IplImage * dst);
The images that we are using in this project only have 3 channels, BGR (in future projects we will be using alpha as the fourth channel.) Therefore, src4/dst4 should be NULL.
Example: cvSplit (bgr, b, g, r, NULL);
Example: cvMerge (b, g, r, NULL, bgr);
IPL_DEPTH_8U - uchar, this is what OpenCV loads images as, just unsigned bytes.
IPL_DEPTH_32F - float, we convert the images into floating point images for you to work with.
BGR
1. Install Mac port from the link http://www.macports.org/
2. Install opencv in terminal: sudo port install opencv
3. Modify PC_Makefile in proj1 like this
cs4670: $(INCLUDE) $(SRC) Project1.cpp
g++ -I/opt/local/include -L/opt/local/lib $(SRC) $(LIBS) -o cs4670 -g
4. Make & run
Good question. Don't use Xcode. Use the terminal, the virtual image we are distributing, or a lab machine.
CV_IMAGE_ELEM( image_header, elemtype, y, x_Nc )
Suppose, we have floating point 1-channel image I (IplImage* img):
I(x,y) ~ CV_IMAGE_ELEM( img, float, y, x);
Suppose, we have floating point 3-channel image I (IplImage* img):
I(x,y)blue ~ CV_IMAGE_ELEM( img, float, y, x*3);
I(x,y)green ~ CV_IMAGE_ELEM( img, float, y, x*3+1);
I(x,y)red ~ CV_IMAGE_ELEM( img, float, y, x*3+2);
These two macros are a bit different and it's not entirely clear why. The first parameter to CV_MAT_ELEM is of type CvMat, NOT CvMat*. Dereference your pointer to CvMat and it should work.
I know at least Ubuntu 9.04 and earlier have an older version of OpenCV in their repositories. 9.04 in particular is broken. The following website has some good advice. Proceed at your own risk since it involves adding a third-party repository. Note, this is just to help you out with the desktop code. I will not be supporting these installations with the Nokia N900 projects.
Here's a funky little quirk of OpenCV. Say you have an image of type uchar. If you display or save this image, OpenCV will expect the pixel values to be between 0-255. If you convert this image to float, then the display function will expect values between 0.0-1.0. HOWEVER, saving an floating point image will still expect the values to be between 0-255. For efficient conversion, you may use the cvConvertScale function.
void cvConvertScale (IplImage * src, IplImage * dst, int scale, int offset);
So a call:
cvConvertScale (image, image, 255, 0);
will multiply all the pixels in image by 255.
Similarly,
cvConvertScale (image, image, 1/255.0, 0);
will divide all the pixels in image by 255.
Requirements: VMware Player, VMware Workstation, or VMware Fusion 64-bit processor that has built in virtualization support (VMware will tell you if it does not)
Windows or Linux: Install VMware Player for free or if you own a copy of VMware Workstation, that will work as well.
Mac: Install a free 30-day trial of VMware Fusion or use the full copy if you own one. (I'll work on a Mac friendly solution since 30-days will not be enough.)
In all three cases, you have the virtual disk image, but you must use VMware to import it. In Workstation or Player, make a custom virtual machine, specify Ubuntu Linux and choose all defaults. Once the machine is built, edit the settings, delete the hard drive and add the image that we have provided to you. In Fusion, simply create a new virtual machine, select continue without disk, and then specify use an existing disk, and point to the location where you saved it.
Password: maemo
I'm also working on proving a VirtualBox version of the vm image. VirtualBox is supported on Windows, Mac, and Linux. However, in Ubuntu 10.04, VirtualBox had an issue with scp over usb. Therefore, it may not necessarily work. If you find yourself in the position where you are using a Mac and do not own VMware Fusion, working on a machine that does not support 64-bit guest OSs, or something similar, Upson 317 does have lab machines that you can use for development. Your CSUG credentials may be used to log in.
Two DVD's will be placed on the right side of the Upson 317 whiteboard. I will soon try to get the image online, but it is about 2GB in size. I hear internal access to Cornell sites is not billed by NUBB.
I did try the latest stable release of VirtualBox for Ubuntu 10.04. For part of the project, you will have to transfer a binary executable to the cell phone that is about 1.7MB. For some reason when you scp or pipe a file over ssh with a USB network connection, at 16KB, the transfer halts and the terminal freezes. I believe this is an implementation bug in the USB passthrough for VirtualBox. If someone has any insight into this issue, let me know.
Email the course staff.
We are currently looking into this.
See the project README for details. They might differ project to project. We will attempt to keep the process as similar as possible.
It shouldn't. If it does, let us know. We tried to design it so they would function in the same way.
maemo
Ubuntu - 192.168.2.14
Nokia N900 - 192.168.2.15
root
password: maemo
Connect the device via USB. Run 'Mad Developer' from the applications menu. Press edit. Press configure.
There is unprotected wifi in Upson 317 called 'cs100r'. Do not use your RedRover credentials.
You have discovered csh. (kmatzen) On my account it defaults to bash. Type:
bash
in the terminal and you should be given a more featured terminal. I'll work on getting it to default to bash.
roboticsXX.csuglab.cornell.edu where XX is between 01 and 11.
The project files that I am constructing for you will compile using g++ and the -g flag. This means that the binary executable is compiled with debug mode enabled. In order to run an executable named 'cs4670' in the debugger, execute the following command:
gdb cs4670
This will take you to the gdb interface. Say for example, you usually run a program by doing the following in the terminal:
./cs4670 -f gaussian -i photo.jpg
To run this program in gdb, it becomes:
r -f gaussian -i photo
You can create breakpoints before running the program. To create a breakpoint, type:
b YourFile.cpp:23
This will create a breakpoint on line 23 of YourFile.cpp.
Alternatively, you can break at a certain function such as:
b your_function
as long as the function name is unambiguous.
Once you hit the break point, you can use the following commands:
n - next (run to the next line in the current scope)
c - continue (run until you hit another breakpoint)
s - step (run until the next line of code even if it's inside a function call)
Finally, to exit:
q
These few commands will get you a long way.
Sometime you will have memory access violations. These are usually indicative of buggy code. However, finding such a bug is not always trivial. A heap analysis tool called memcheck is super useful. It is the default tool used by valgrind. In order to run valgrind on a program:
valgrind ./cs4670 -f gaussian -i photo.jpg
This will print a list of errors that can be overwhelming. Be patient and try to comprehend the errors. A common error is:
Invalid write of size 4
==26689== at 0x100000F12: main (in ./a.out)
==26689== Address 0x100358108 is 0 bytes after a block of size 40 alloc'd
==26689== at 0x10001033A: operator new[](unsigned long) (vg_replace_malloc.c:305)
==26689== by 0x100000F05: main (in ./a.out)
What is key to notice here in my example is that there is a write of size four 0 bytes outside of a block of allocated memory. This should set off a red flag that you have an off-by-one array index error. I was using 32-bit integers (four bytes) and 0 bytes outside of a block means it happened right afterwards.
Furthermore, valgrind will tell you where you have memory leaks. The following example illustrates this concept:
HEAP SUMMARY:
==26689== in use at exit: 128 bytes in 2 blocks
==26689== total heap usage: 2 allocs, 0 frees, 128 bytes allocated
==26689==
==26689== LEAK SUMMARY:
==26689== definitely lost: 40 bytes in 1 blocks
==26689== indirectly lost: 0 bytes in 0 blocks
==26689== possibly lost: 0 bytes in 0 blocks
==26689== still reachable: 88 bytes in 1 blocks
==26689== suppressed: 0 bytes in 0 blocks
==26689== Rerun with --leak-check=full to see details of leaked memory
This tells me that I lost 40 bytes in the process. To give you some insight, I allocated an array of 10 4-byte integers and did not delete them. If I follow the advice and add --leak-check=full I get the following:
40 bytes in 1 blocks are definitely lost in loss record 1 of 2
==26695== at 0x10001033A: operator new[](unsigned long) (vg_replace_malloc.c:305)
==26695== by 0x100000F05: main (in ./a.out)
Which tells me that I made a call to new[] in main which leaked the memory.
You may be familiar with the Java standard libraries. C++ has something similar and I highly recommend that you leverage it whenever possible. This library provides time complexity specifications alongside the documentation which can be really powerful and rarely found in other standard libraries. By leveraging existing, tested code, you can not only reduce your work, but also the work of the grader (they know the libraries work and do not have to scrutinize them.) cplusplus.com is an excellent resource. I'll give you an example of a useful way to use the standard library for C++, also known as the Standard Template Library or STL.
Say we have a series of values and we want to find the median. What's the best way to do this? I'm going to show you an efficient and simple method that involves storing the values, sorting them, and then taking the median.
Say we have (2*k+1)^2 such values and they are floats.
std::vector<float> values;
// we want to preallocate the necessarily memory. it takes time to potentially
// reallocate each time we add a value. just do it once
int numValues = (2*k+1)*(2*k+1);
values.reserve (numValues);
// now we want to add the values
for (int i = 0; i < numValues); ++i) //side note: why is ++i faster than i++ ?
{
values.push_back (some_value_from_somewhere);
}
// so now we have our vector of values, how do we sort it? Use iterators!
std::sort (values.begin(), values.end());
// and finally, we want to take the median (middle value)
float median = values [values.size()/2];
And there you have it. Finding the median using the STL and NO CUSTOM CODE! Makes both our lives easier, right?
You've discovered emacs. If you can contort your hand in funny ways, then the keyboard shortcuts will make you feel right at home. vim is installed and available from the terminal. Furthermore, you can use Gedit available from the applications menu.
(kmatzen) I don't have a personal issue with this matter. I'm interested in seeing if you learned the core computer vision concepts. I'm also interested in whether or not you respected the performance limitations of a mobile platform. For example, I don't want to see a final project where someone made an application that requires a 2GHz processor just to run reasonably. When designing the final project, keep things within a mobile platform scope. I will need to at least be able to run the code on my machine in some sort of emulator. I shouldn't need to have a whole cross-compiler build environment installed in order to do so. A single executable to install an emulator and a package to deploy to the emulator would be appreciated. Keep in mind that I will be testing on an Upson 317 lab machine (Ubuntu 10.04).