OpenCV Image Sharpening(Can't find the MISTAKE in my code) - opencv

void sharpen(IplImage *in,IplImage *out)
{
int r=in->height;
int c=in->width;
int st=in->widthStep;
int i,j;
for(i=1;i<r-1;i++)
{
uchar *cur=(uchar *)(in->imageData+i*st);
uchar *pre=(uchar *)(in->imageData+(i-1)*st);
uchar *next=(uchar *)(in->imageData+(i+1)*st);
uchar *output=(uchar *)(out->imageData+i*st);
for(j=3;j<c*3-3;j++)
{
*output=uchar(5*cur[j]-cur[j-3]-cur[j+3]-pre[j]-next[j]);
*output++;
}
}
}
OpenCV Image sharpening using Laplacian...
Would you mind finding out mistakes for me?

One obvious mistake is that:
*output++;
should be:
output++;
i.e. you just need to increment the pointer, not dereference it. But I don't think that's your only bug.

Related

byte array in arduino library

ok so here is one for you maybe simple but i am not so sure.
i have the following code and it may be clear what i wish to do by looking at the code.
Arduino.ino
RF myRF; //Creation of RF class.
const int dataSize = 500;
byte storedData[dataSize];
//array is populated through program then the following is called
myRF.populate(storedData);
RF.CCP
const int dataSize = 500;
byte recivedData[dataSize];
void RF::populate(byte reciveddata){
recivedData = reciveddata;
}
RF.H
#include Arduino.h
#ifndef RF_H
#define RF_H
class RF {
public:
RF();
~RF();
void recive();
void send();
void print();
void sendnew(byte Storeddata);
};
#endif
this is however producing an error "byte is not declared"
Hope its clear what i intend to do and hope you can help thanks.
There are two problems in your files:
h file:
#include Arduino.h
You should write
#include <Arduino.h>
c file:
const int dataSize = 500;
byte recivedData[dataSize];
void RF::populate(byte reciveddata){
recivedData = reciveddata;
}
Here you have a big problem. You are declaring recivedData here, but you want to assign it a value coming from another part of the program. This is not how it works.
IMO you have two ways to do this.
1) store just the pointer to the memory; this way is faster and occupies less memory than solution 2, but you have to ensure that the storedData variable you pass in the .ino file is not changed during the function
#include "RF.h" // I hope you already included this
byte *recivedData;
void RF::populate(byte *reciveddata){
recivedData = reciveddata;
}
2) copy the content of the received array to this array; this way you have a copy of the array, so you occupy twice the memory (but you can edit storedData without problems).
#include "RF.h" // I hope you already included this
const int dataSize = 500;
byte recivedData[dataSize];
int recivedDataLength;
void RF::populate(byte *reciveddata, int reciveddatalength){
recivedDataLength = (reciveddatalength>dataSize) ? dataSize : reciveddatalength;
for (int i = 0; i < recivedDataLength; i++)
recivedData[i] = reciveddata[i];
}

Handling a vector of cv::Mat with a Method

I want to give a method a vector to fill it with a different number of Mat Objects, something like this:
int main()
{
vector<cv::Mat> areas;
doSomething(areas);
return 0;
}
doSomething(vector<cv::Mat> &areas)
{
cv::Mat first = zeros(...
cv::Mat second = ....
cv::Mat third = ...
areas.push_back(first);
areas.push_back(second);
areas.push_back(third);
}
Of course that doesn't work, because there is not enough memory allocated at the begin and the memory is only on the stack!
A second idea I had is to make pointers:
int main()
{
vector<cv::Mat> *areas = new vector<cv::Mat>();
doSomething(&areas);
return 0;
}
doSomething(vector<cv::Mat> *areas)
{
cv::Mat first = zeros(...
cv::Mat second = ....
cv::Mat third = ...
areas->push_back(first);
areas->push_back(second);
areas->push_back(third);
}
But again the problem is, that I have no idea at the beginning how much space is to allocate.
The third idea was to return the vector at the "normal" way:
int main()
{
vector<cv::Mat> areas;
areas = doSomething();
return 0;
}
vector<cv::Mat> doSomething()
{
vector<cv::Mat> areas;
cv::Mat first = zeros(...
cv::Mat second = ....
cv::Mat third = ...
areas->push_back(first);
areas->push_back(second);
areas->push_back(third);
return areas;
}
In this case of course only the headers of the vector was copied and not the Mat Objects in the vector
Do you have any idea how i am able to solve this problem?
Thanks in advance!

Explanation of IplImage* img

I just started learning OpenCV with "Learning OpenCV Computer Vision with the OpenCV Library".
In the first example which demonstrates how to display a picture, it has a line
IplImage* img = cvLoadImage("name.type")
Although the book explains it, I still do not fully know what exactly IplImage* img does.
Does cvLoadImage loads the image to img which IplImage is pointing to? Can anyone explain this to me please? Thank you
img is the name of the variable, might as well be blahblahblah;
IplImage is the type of the variable, it's just a struct that contains the image data itself plus some info (size, color depth, etc.) on the image;
typedef struct _IplImage {
int nSize;
int ID;
int nChannels;
int alphaChannel;
int depth;
char colorModel[4];
char channelSeq[4];
int dataOrder;
int origin;
int align;
int width;
int height;
struct _IplROI* roi;
struct _IplImage* maskROI;
void* imageId;
struct _IplTileInfo* tileInfo;
int imageSize;
char* imageData;
int widthStep;
int BorderMode[4];
int BorderConst[4];
char* imageDataOrigin;
} IplImage;
For more info on IplImage: Other question about IplImage
cvLoadImage provides a pointer to an IplImage, which means it creates an IplImage when it loads it and returns you it's emplacement.
Do not forget to do cvReleaseImage(&img) when you are finished with it, if you do not want to have memory leaks.

OpenCV Mat element types and their sizes

I'm confused by the OpenCV Mat element types. This is from the docs:
There is a limited fixed set of primitive data types the library can operate on.
That is, array elements should have one of the following types:
8-bit unsigned integer (uchar)
8-bit signed integer (schar)
16-bit unsigned integer (ushort)
16-bit signed integer (short)
32-bit signed integer (int)
32-bit floating-point number (float)
64-bit floating-point number (double)
...
For these basic types, the following enumeration is applied:
enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };
It's known that C++ standard doesn't define the size of basic types in bytes, so how do they use such assumptions? And what type should I expect from, let's say, CV_32S, is it int32_t or int?
Developing from Miki's answer,
In OpenCV 3 definition has moved to modules/core/include/opencv2/core/traits.hpp, where you can find:
/** #brief A helper class for cv::DataType
The class is specialized for each fundamental numerical data type supported by OpenCV. It provides
DataDepth<T>::value constant.
*/
template<typename _Tp> class DataDepth
{
public:
enum
{
value = DataType<_Tp>::depth,
fmt = DataType<_Tp>::fmt
};
};
template<int _depth> class TypeDepth
{
enum { depth = CV_USRTYPE1 };
typedef void value_type;
};
template<> class TypeDepth<CV_8U>
{
enum { depth = CV_8U };
typedef uchar value_type;
};
template<> class TypeDepth<CV_8S>
{
enum { depth = CV_8S };
typedef schar value_type;
};
template<> class TypeDepth<CV_16U>
{
enum { depth = CV_16U };
typedef ushort value_type;
};
template<> class TypeDepth<CV_16S>
{
enum { depth = CV_16S };
typedef short value_type;
};
template<> class TypeDepth<CV_32S>
{
enum { depth = CV_32S };
typedef int value_type;
};
template<> class TypeDepth<CV_32F>
{
enum { depth = CV_32F };
typedef float value_type;
};
template<> class TypeDepth<CV_64F>
{
enum { depth = CV_64F };
typedef double value_type;
};
In most of the cases/compilers you should be fine using C++ exact data types. You wouldn't have problems with single byte data types (CV_8U -> uint8_t and CV_8U -> int8_t) as unambiguously defined in C++. The same for float (32bit) and double (64bit). However, it is true that for other data types to be completely sure you use the correct data type (for example when using the at<> method) you should use for example:
typedef TypeDepth<CV_WHATEVER_YOU_USED_TO_CREATE_YOUR_MAT>::value_type access_type;
myMat.at<access_type>(y,x) = 0;
As a side note, I am surprised they decided to take such an ambiguous approach, instead of simply using exact data types.
Therefore, regarding your last question:
What type should I expect from, let's say, CV_32S?
I believe the most precise answer, in OpenCV 3, is:
TypeDepth<CV_32S>::value_type
In core.hpp you can find the following:
/*!
A helper class for cv::DataType
The class is specialized for each fundamental numerical data type supported by OpenCV.
It provides DataDepth<T>::value constant.
*/
template<typename _Tp> class DataDepth {};
template<> class DataDepth<bool> { public: enum { value = CV_8U, fmt=(int)'u' }; };
template<> class DataDepth<uchar> { public: enum { value = CV_8U, fmt=(int)'u' }; };
template<> class DataDepth<schar> { public: enum { value = CV_8S, fmt=(int)'c' }; };
template<> class DataDepth<char> { public: enum { value = CV_8S, fmt=(int)'c' }; };
template<> class DataDepth<ushort> { public: enum { value = CV_16U, fmt=(int)'w' }; };
template<> class DataDepth<short> { public: enum { value = CV_16S, fmt=(int)'s' }; };
template<> class DataDepth<int> { public: enum { value = CV_32S, fmt=(int)'i' }; };
// this is temporary solution to support 32-bit unsigned integers
template<> class DataDepth<unsigned> { public: enum { value = CV_32S, fmt=(int)'i' }; };
template<> class DataDepth<float> { public: enum { value = CV_32F, fmt=(int)'f' }; };
template<> class DataDepth<double> { public: enum { value = CV_64F, fmt=(int)'d' }; };
template<typename _Tp> class DataDepth<_Tp*> { public: enum { value = CV_USRTYPE1, fmt=(int)'r' }; };
You can see that CV_32S is the value for the type int, not int32_t.
While C++ doesn't define the size of an element, the question is hypothetical: for systems OpenCV is run on, the sizes are known. Given
cv::Mat m(32,32,CV_32SC1, cv:Scalar(0));
std::cout << "size of the element in bytes: " << m.depth() << std::endl;
std::cout << "or " << m.step.p[ m.dims-1 ]/m.channels() << std::endl;
So how can you be sure it is int?
An attempt to call
int pxVal = m.at<int>(0,0);
will
CV_DbgAssert( elemSize()==sizeof(int) );
Where the left hand is defined via the cv::Mat::flags -- in this example as the predefined depth of the CV_32SC1 equal to
CV_DbgAssert( m.depth() == sizeof(int) )
or
CV_DbgAssert( 4 == sizeof(int) )
So if you succeeded you are left only the endianness. And that was checked when the cvconfig.h was generated (by CMake).
TL;DR, expect the types given in the header and you'll be fine.
You can find all definitions on your questions in opencv's sources.
See https://github.com/Itseez/opencv/blob/master/modules/core/include/opencv2/core/cvdef.h file.
I have found several #define in OpenCV's code related to CV_8UC1, CV_32SC1, etc. To make the enumerations work, OpenCV put additional codes to convert the plain numbers together as a parameter (i.e, CV_8UC1, CV_16UC2...are all represented by their respective numbers), and break the depth and channels apart in the definition of CvMat(I guess Mat may have similar codes in its definition). Then, it uses create() to allocate spaces for the matrix. Since create() is inline, I can only guess that it is similar to malloc() or something.
As source codes changes a lot from 2.4.9 to 3.0.0, I need to post more evidence later. Please allow me a little time to find out more and edit my answer.
In short the table you provided is correct.
If you want to directly access a pixel, you typecast it to the specifier to the right, for example CV_32S is a signed 32-bit.
The S always means a signed integral number (signed char, signed short, signed int)
The F always means a floating point number (float, double)
The U always means an unsigned integral number.
The enumeration is used only when creating or converting a Mat. It's a way of telling the mat which is the desired type, as I understand it it's the C predecessor to when templates were not used.
I use the C functionality exclusively, and in order to create an image, it would be an error to pass the following:
cvCreateImage(mySize,char, nChannels);
Instead, I pass the following:
cvCreateImage(mySize, IPL_DEPTH_8U, nChannels);
Here, the IPL_DEPTH_8U is a flag that is used by the function. The function itself has a switch-type statement that checks the flag. The actual value of the flag is most often meaningless as it's most often controlled by conditional, not algebraic statements.

BCB 6.0 "raised exception class EAccessViolation with message 'Access violation at address'"

I'm newer to C++. I have written some code, but when i run it, there's always this:
raised exception class
EAccessViolation with message 'Access
violation at address'
i don't understand this. Would you like to help me solve it? It's important to me. Really, really thank you!
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <math.h>
#include <conio.h>
#define k 2
#define minoffset 0.5
using namespace std;
struct Point
{
double X;
double Y;
};
vector<Point> dataprocess();
void k_means(vector<Point> points,int N);
double getdistance(Point p1,Point p2)
{ double distance;
distance=sqrt((p1.X-p2.X)*(p1.X-p2.X)+(p1.Y-p2.Y)*(p1.Y-p2.Y));
return distance;
}
int getmindis(Point p,Point means[])
{
int i;
int c;
double dis=getdistance(p,means[0]);
for(i=1;i<k;i++)
{
double term=getdistance(p,means[i]);
if(term<dis)
{
c=i;
dis=term;
}
}
return c;
}
Point getmeans(vector<Point> points)
{
int i;
double sumX,sumY;
Point p;
int M=points.size();
for(i=0;i<M;i++)
{
sumX=points[i].X;
sumY=points[i].Y;
}
p.X=sumX/M;
p.Y=sumY/M;
return p;
}
int main()
{ int N;
vector<Point> stars;
stars=dataprocess();
N=stars.size();
cout<<"the size is:"<<N<<endl;
k_means(stars,N);
getch();
}
vector<Point> dataprocess()
{
int i;
int N;
double x,y;
vector<Point> points;
Point p;
string import_file;
cout<<"input the filename:"<<endl;
cin>>import_file;
ifstream infile(import_file.c_str());
if(!infile)
{
cout<<"read error!"<<endl;
}
else
{
while(infile>>x>>y)
{
p.X=x;
p.Y=y;
points.push_back(p);
}
}
N=points.size();
cout<<"output the file data:"<<endl;
for(i=0;i<N;i++)
{
cout<<"the point"<<i+1<<"is:X="<<points[i].X<<" Y="<<points[i].Y<<endl;
}
return points;
}
void k_means(vector<Point> points,int N)
{
int i;
int j;
int index;
vector<Point> clusters[k];
Point means[k];
Point newmeans[k];
double d,offset=0;
bool flag=1;
cout<<"there will be"<<k<<"clusters,input the original means:"<<endl;
for(i=0;i<k;i++)
{
cout<<"k"<<i+1<<":"<<endl;
cin>>means[i].X>>means[i].Y;
}
while(flag)
{
for(i=0;i<N;i++)
{
index=getmindis(points[i],means);
clusters[index].push_back(points[i]);
}
for(j=0;j<k;j++)
{
newmeans[j]=getmeans(clusters[j]);
offset=getdistance(newmeans[j],means[j]);
}
if(offset>d)
{
d=offset;
}
flag=(minoffset<d)?true:false;
for(i=0;i<k;i++)
{
means[i]=newmeans[i];
clusters[i].clear();
}
}
for(i=0;i<k;i++)
{
cout<<"N"<<i+1<<"="<<clusters[i].size()<<endl;
cout<<"the center of k"<<i+1<<"is:"<<means[i].X<<" "<<means[i].Y<< endl;
}
}
You surely have some algo errors in you code. It is difficult to deal with code without input data, that caused an error, but let's try:
First, lets look at function Point getmeans(vector<Point> points)
it is supposed to evaluate mean coordinates for cluster of points: if you pass an empty cluster to this function it will cause an error:
look here -
int M=points.size()
and here -
for(i=0;i<M;i++)
{
sumX=points[i].X;
sumY=points[i].Y;
}
if your cluster is empty than M will be zero and you loop will iterate 2^31 times (until 32 bit integer overflow) and each time you will try to read values of nonexistent vector items
So, You have to test if you vector is not empty before running main function loop and you have to decide which mean values should be assigned for zero cluster (May be you need an additional flag for empty cluster which will be checked before dealing with cluster's mean values)
Then lets examine function int getmindis(Point p,Point means[]) and, also, a place, where we call it:
index=getmindis(points[i],means); clusters[index].push_back(points[i]);
This function assings points to clusters. cluster number is ruled by c variable. If input point doesn't fit to any cluster, function will return uninitialized variable (holding any possible value) which. then is used as vector index of nonexisting element - possible access violation error
You probably have to initialize c to zero in declaration
Tell us when you will be ready with errors described above and also show us a sample input file (one which causes errors, if all datasets cause errors, show us the smallest one)

Resources