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);
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'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.
How do I convert an array<System:Byte>^ to a Mat in openCV. I am being passed a array<System:Byte>^ in c++/cli, but I need to convert it to Mat to be able to read it and display it.
You can use constructor Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP). The conversion may look like this.
void byteArray2Mat(array<System::Byte>^ byteArray, cv::Mat &output)
{
pin_ptr<System::Byte> p = &byteArray[0];
unsigned char* pby = p;
char* pch = reinterpret_cast<char*>(pby);
// assuming your input array has 2 dimensions.
int rows = byteArray->GetLength(0);
int cols = byteArray->GetLength(1);
output = cv::Mat(rows, cols, CV_8UC1, (void*)pch)
}
I don't have c++/CLI to test the program and this may not be most efficient method. At least it should give you an idea on how to get started.
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).
How do I convert a cv::Mat of type CV_32FC1 to the type CV_64FC1 (equivalent to a change from float to double)?
I am opening a Matrix that was saved as XML (cvSave) but as a float. This means that the field <dt> has the value f in the file. I need to change it to d to open it. But I'd rather not do this, instead I'd like to open it directly as a Matrix with elements of type double, or convert it later from float to double.
Below is my code for opening the file.
/** Load cv::Mat from XML file.
*/
cv::Mat loadMat(const std::string filename)
{
cv::Mat result;
cv::FileStorage fs(filename, cv::FileStorage::READ);
fs.getFirstTopLevelNode() >> result;
return result;
}
Okay, I'm a dimwit. Here is how it goes:
There is the function convertTo that does exactly what I want.
Thanks for matrix type conversion in opencv for pointing this out.
Here is how I do it:
cv::Mat A = loadMat("mymat.xml"); // See function loadMat in the question!
A.convertTo(A, CV_64F);