I'm looking for a solution to display successive frames in one window using OpenCV. I have a sequence of images (001.jpg, 002.jpg, 003.jpg, etc.), but not a video. I have to display them within a loop.
The standard code to display an image is:
IplImage* src = cvLoadImage("001.jpg");
cvNamedWindow("My pic");
cvShowImage("My pic",src);
cvWaitKey();
As Link suggests, one option would be to write a function that automatically generates the correct filename, for example:
void loadImage(IplImage *image, int number)
{
// Store path to directory
char filename[100];
strcpy(filename, "/path/to/files");
// Convert integer to char
char frameNo[10];
sprintf(frame, "%03i", number);
// Combine to generate path
strcat(filename, frameNo);
strcat(filename, ".bmp");
// Use path to load image
image = cvLoadImage(filename);
}
This could then be used in a loop for a known number of images
IplImage *im;
for (int i = 0; i < nImages; ++i)
{
loadImage(im, i);
/*
Do stuff with im
*/
}
An alternative option would be to investigate the boost directory iterator.
#Chris code works, I want to add an even simpler routine
void loadImage()
{
int nImages = 6;
for (int i = 0; i < nImages; ++i)
{
IplImage *image;
char filename[100];
strcpy(filename, "images/");
char frameNo[10];
sprintf(frameNo, "%03i", i);
strcat(filename, frameNo);
strcat(filename, ".jpg");
image = cvLoadImage(filename);
cvNamedWindow("pic");
cvShowImage("pic",image);
cvWaitKey(1000);
}
}
Try to use XML/YAML persistence mechanisms of OpenCV. Write a list of image paths for loading and use a loop to read those paths and load images. In the example of stereo calibration such a list is used (there is a directory with examples installed with OpenCV).
Related
I want to count the total non-zero points number in an image using OpenCL.
Since it is an adding work, I used the atom_inc.
And the kernel code is shown here.
__kernel void points_count(__global unsigned char* image_data, __global int* total_number, __global int image_width)
{
size_t gidx = get_global_id(0);
size_t gidy = get_global_id(1);
if(0!=*(image_data+gidy*image_width+gidx))
{
atom_inc(total_number);
}
}
My question is, by using atom_inc it will be much redundant right?
Whenever we meet a non-zero point, we should wait for the atom_inc.
I have a idea like this, we can separate the whole row into hundreds groups, we find the number in different groups and add them at last.
If we can do something like this:
__kernel void points_count(__global unsigned char* image_data, __global int* total_number_array, __global int image_width)
{
size_t gidx = get_global_id(0);
size_t gidy = get_global_id(1);
if(0!=*(image_data+gidy*image_width+gidx))
{
int stepy=gidy%10;
atom_inc(total_number_array+stepy);
}
}
We will separate the whole problem into more groups.
In that case, we can add the numbers in the total_number_array one by one.
Theoretically speaking, it will have a great performance improvement right?
So, does anyone have some advice about the summing issue here?
Thanks!
Like mentioned in the comments this is a reduction problem.
The idea is to keep separate counts and then put them back together at the end.
Consider using local memory to store the values.
Declare a local buffer to be used by each work group.
Keep track of the number of occurrences in this buffer by using the local_id as the index.
Sum these values at the end of execution.
A very good introduction to the reduction problem using Opencl is shown here:
http://developer.amd.com/resources/documentation-articles/articles-whitepapers/opencl-optimization-case-study-simple-reductions/
The reduction kernel could look like this (taken from the link above):
__kernel
void reduce(
__global float* buffer,
__local float* scratch,
__const int length,
__global float* result) {
int global_index = get_global_id(0);
int local_index = get_local_id(0);
// Load data into local memory
if (global_index < length) {
scratch[local_index] = buffer[global_index];
} else {
// Infinity is the identity element for the min operation
scratch[local_index] = INFINITY;
}
barrier(CLK_LOCAL_MEM_FENCE);
for(int offset = get_local_size(0) / 2;
offset > 0;
offset >>= 1) {
if (local_index < offset) {
float other = scratch[local_index + offset];
float mine = scratch[local_index];
scratch[local_index] = (mine < other) ? mine : other;
}
barrier(CLK_LOCAL_MEM_FENCE);
}
if (local_index == 0) {
result[get_group_id(0)] = scratch[0];
}
}
For further explanation see the proposed link.
I know these iterator questions have been asked and answered a thousand times, however when I compile the following code, I still get this error:
error C2440: 'initializing' : cannot convert from
'std::_Vector_iterator<_Myvec>' to 'cv::Vector<_Tp> *'
.
void iterate(vector<vector<cv::Point> >& contours){
Vector<Vector<cv::Point>>::iterator it = contours.begin();
for( int i = 0; i< contours.size(); i++ ){
if(contourArea(contours[i])>1000){
it++;
}else{
contours.erase(it);
}
}
}
I don't see anything wrong with this code. The template type of the vector for the new iterator is the same like the vector I'm getting the iterator from.
Can not convert errors are generally very literal. Often the types used can give hints where in your code somethng is wrong.
Here we have the use of uppercase Vector class to define your iterator, and you are assigning a lowercase Vector class to it.
Note you would probably have gotten a different error if Vector was not a real class.
I'm writing a simple program that extracts descriptors from images and writes them to files.
I'm saving the descriptors in a Mat variable, but I'm getting wrong values when trying to access them.
Here is the code:
string s = format("%s\\%s\\img%d.ppm", dataset_dir.c_str(), dsname, k);
Mat imgK = imread(s, 0);
if( imgK.empty() )
break;
detector->detect(imgK, kp);
descriptor->compute(imgK, kp, desc);
//writing the descriptors to a file
char fileName[512];
sprintf(fileName,"C:\\BinaryDescriptors\\OpenCVRes\\%s\\%s\\Descriptors%d.txt",descriptor_name,dsname,k);
FILE * fid;
fid=fopen(fileName,"a+");
for (int ix=0; ix< kp.size(); ix++){
fprintf(fid,"%f \t%f", kp[ix].pt.x,kp[ix].pt.y);
fprintf(fid, "\t1 \t0 \t1");
fflush(fid);
//writing the descriptor
for (int jx=0;jx<desc.cols;jx++){
int gil = desc.at<int>(ix,jx);
printf("AAAA %d", gil);
fprintf(fid,"\t%d",desc.at<int>(ix,jx));
fflush(fid);
}
}
fprintf(fid,"\n");
fclose(fid);
The line where I'm accessing the descriptors matrix is int gil = desc.at int(ix,jx); Is there something I'm doing wrong?
Any help will be greatly appreciated, as I'm quite stuck :)
Thanks,
Gil.
You are accessing the descriptor matrix with int, so that the matrix must be of type CV_32SC1. Are you sure it is that type? Most of the descriptors are coded with float (CV_32F) or unsigned char (CV_8U). Check that desc.type() == CV_32SC1.
By the way, you should use cv::FileStorage to save and load descriptors, it is much easier than directly accessing files.
Im using classes to create a function. The function must find a selected colour in the image provided. So I made it so that the function takes a Vec3b value since it is an RGB value we are talking about.
class colorcompare
{
private:
int threshold;
Vec3b color;
void setcolor(Vec3b);
Mat process(Mat&);
void setthresh(const int);
int getdist(Vec3b);
};
void colorcompare::setcolor(Vec3b colr)
{
color = colr;
}
int _tmain(int argc, _TCHAR* argv[])
{
colorcompare cc1;
Mat image;
image = imread("c:\\car2.jpg", -1);
cc1.setcolor(19,69,139); //This is where im getting error
cc1.setthresh(100);
namedWindow("meh");
imshow("meh", cc1.process(image));
waitKey(0);
return 0;
}
Now the error I am getting is this: 'colorcompare::setcolor' : function does not take 3 arguments
I know that vec3b is a vector of 3 values, so in other words I can access the individual values of vec3b as color[0], color[1] and color[2].
And I know I can define it like such in the function above but it shouldnt the vec3b be able to take 3 values? Like I did in my code?
Classic mistake: the function expects a cv::Vec3b object, not 3 int variables.
If you want a single line solution, try this:
cc1.setcolor(cv::Vec3b(19,69,139));
You defined setColor to take a Vec3b as parameter, so you should give it a Vec3b:
cv::Vec3b color(19,69,139); // or cv::Vec3b color; color[0]=19, ...
cc1.setColor(color);
I have a binary file I've loaded using an NSData object. Is there a way to locate a sequence of characters, 'abcd' for example, within that binary data and return the offset without converting the entire file to a string? Seems like it should be a simple answer, but I'm not sure how to do it. Any ideas?
I'm doing this on iOS 3 so I don't have -rangeOfData:options:range: available.
I'm going to award this one to Sixteen Otto for suggesting strstr. I went and found the source code for the C function strstr and rewrote it to work on a fixed length Byte array--which incidentally is different from a char array as it is not null terminated. Here is the code I ended up with:
- (Byte*)offsetOfBytes:(Byte*)bytes inBuffer:(const Byte*)buffer ofLength:(int)len;
{
Byte *cp = bytes;
Byte *s1, *s2;
if ( !*buffer )
return bytes;
int i = 0;
for (i=0; i < len; ++i)
{
s1 = cp;
s2 = (Byte*)buffer;
while ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2)
return cp;
cp++;
}
return NULL;
}
This returns a pointer to the first occurrence of bytes, the thing I'm looking for, in buffer, the byte array that should contain bytes.
I call it like this:
// data is the NSData object
const Byte *bytes = [data bytes];
Byte* index = [self offsetOfBytes:tag inBuffer:bytes ofLength:[data length]];
Convert your substring to an NSData object, and search for those bytes in the larger NSData using rangeOfData:options:range:. Make sure that the string encodings match!
On iPhone, where that isn't available, you may have to do this yourself. The C function strstr() will give you a pointer to the first occurrence of a pattern within the buffer (as long as neither contain nulls!), but not the index. Here's a function that should do the job (but no promises, since I haven't tried actually running it...):
- (NSUInteger)indexOfData:(NSData*)needle inData:(NSData*)haystack
{
const void* needleBytes = [needle bytes];
const void* haystackBytes = [haystack bytes];
// walk the length of the buffer, looking for a byte that matches the start
// of the pattern; we can skip (|needle|-1) bytes at the end, since we can't
// have a match that's shorter than needle itself
for (NSUInteger i=0; i < [haystack length]-[needle length]+1; i++)
{
// walk needle's bytes while they still match the bytes of haystack
// starting at i; if we walk off the end of needle, we found a match
NSUInteger j=0;
while (j < [needle length] && needleBytes[j] == haystackBytes[i+j])
{
j++;
}
if (j == [needle length])
{
return i;
}
}
return NSNotFound;
}
This runs in something like O(nm), where n is the buffer length, and m is the size of the substring. It's written to work with NSData for two reasons: 1) that's what you seem to have in hand, and 2) those objects already encapsulate both the actual bytes, and the length of the buffer.
If you're using Snow Leopard, a convenient way is the new -rangeOfData:options:range: method in NSData that returns the range of the first occurrence of a piece of data. Otherwise, you can access the NSData's contents yourself using its -bytes method to perform your own search.
I had the same problem.
I solved it doing the other way round, compared to the suggestions.
first, I reformat the data (assume your NSData is stored in var rawFile) with:
NSString *ascii = [[NSString alloc] initWithData:rawFile encoding:NSAsciiStringEncoding];
Now, you can easily do string searches like 'abcd' or whatever you want using the NSScanner class and passing the ascii string to the scanner. Maybe this is not really efficient, but it works until the -rangeOfData method will be available for iPhone also.