Laplacian does not give desired output - c++

Here is my code:
int Factor=3,offset=0,k,l,p,q;
IplImage * image = cvCreateImage(cvSize(img->width, img->height),img->depth, img->nChannels);
cvCopy (img, image, 0);
long double mean=0,nTemp=0,c,sum=0,n=0,s=0,d=0;
int i=0,j=0,krow,kcol;
kernel[0][0]=kernel[0][2]=kernel[2][0]=kernel[2][2]=0;
kernel[0][1]=kernel[1][0]=kernel[1][2]=kernel[2][1]=1;
kernel[1][1]=-4;
uchar* temp_ptr=0 ;
int rows=image->height,cols=image->width,row,col;
//calculate the mean of image and deviation
for ( row = 1; row < rows - 2; row++ )
{
for ( col = 1; col < cols - 2; col++ )
{
nTemp = 0.0;
for (p=0, krow = -1 ; p < 3; krow++,p++)
{
for (q=0, kcol = -1; q < 3; kcol++,q++)
{
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*(row+krow))))[(col+kcol)*3];
for(int k=0; k < 3; k++)
Pixel[p][q].val[k]=temp_ptr[k];
}
}
for (i=0 ; i < 3; i++)
{
for (j=0 ; j < 3; j++)
{
c = (Pixel[i][j].val[0]+Pixel[i][j].val[1]+Pixel[i][j].val[2])/Factor ;
nTemp += (double)c * kernel[i][j];
}
}
sum += nTemp;
n++;
}
}
mean = ((double)sum / n);
for ( row = 1; row < rows - 2; row++ )
{
for ( col = 1; col < cols - 2; col++ )
{
nTemp = 0.0;
for (p=0, krow = -1 ; p < 3; krow++,p++)
{
for (q=0, kcol = -1; q < 3; kcol++,q++)
{
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*(row+krow))))[(col+kcol)*3];
for(int k=0; k < 3; k++)
Pixel[p][q].val[k]=temp_ptr[k];
}
}
for (i=0 ; i < 3; i++)
{
for (j=0 ; j < 3; j++)
{
c = (Pixel[i][j].val[0]+Pixel[i][j].val[1]+Pixel[i][j].val[2])/Factor ;
nTemp += (double)c * kernel[i][j];
}
}
s = (mean - nTemp);
d += (s * s);
}
}
d = d / (n - 1);
d = (sqrt(d));
d=d* 2;
// Write to image
for ( row = 1; row < rows - 2; row++ )
{
for ( col = 1; col < cols - 2; col++ )
{
nTemp = 0.0;
for (p=0, krow = -1 ; p < 3; krow++,p++)
{
for (q=0, kcol = -1; q < 3; kcol++,q++)
{
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*(row+krow))))[(col+kcol)*3];
for(int k=0; k < 3; k++)
Pixel[p][q].val[k]=temp_ptr[k];
}
}
for (i=0 ; i < 3; i++)
{
for (j=0 ; j < 3; j++)
{
c = (Pixel[i][j].val[0]+Pixel[i][j].val[1]+Pixel[i][j].val[2])/Factor ;
nTemp += (double)c * kernel[i][j];
}
}
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row)))[col*3];
if (nTemp > d)
temp_ptr[0]=temp_ptr[1]=temp_ptr[2]=255;
else
temp_ptr[0]=temp_ptr[1]=temp_ptr[2]=0;
}
}
Where am i going wrong? I have implemented Gaussian Filtering in a similar manner, is there anything wrong in my algorithm?

It seems that your code (labeled "Write to image") overwrites the input image during the calculations. This is not good. Create a copy of the image, calculate its pixels, then delete the original image.

I noticed is that your code is needlessly complex and inefficient. You don't need to convolve the image before calculating its mean — the convolution just multiplies the mean by the sum of the kernel entries.
Also, since your convolution kernel sums to zero, the mean you get after convolving with it will also (almost) be zero. The only non-zero contributions will come from the edges of the image. I rather doubt that's actually what you want to calculate (and if it is, you could save a lot of time by summing only over the edges in the first place).
Third, as pointed out in another answer (I missed this one myself), you're not averaging over all the color channels, you're averaging over the red channel three times. (Besides, you should probably use a weighted average anyway, after applying gamma correction.)
And finally, as anatolyg said, you're overwriting the image data before you're done reading it. There are several ways to fix that, but the easiest is to write your output to a separate buffer.

Related

Laplacian Sharpening result is kinda greyish C++

I am trying to implement laplacian filter for sharpening an image.
but the result is kinda grey , I don't know what went wrong with my code.
Here's my work so far
img = imread("moon.png", 0);
Mat convoSharp() {
//creating new image
Mat res = img.clone();
for (int y = 0; y < res.rows; y++) {
for (int x = 0; x < res.cols; x++) {
res.at<uchar>(y, x) = 0.0;
}
}
//variable declaration
//change -5 to -4 for original result.
int filter[3][3] = { {0,1,0},{1,-4,1},{0,1,0} };
//int filter[3][3] = { {-1,-2,-1},{0,0,0},{1,2,1} };
int height = img.rows;
int width = img.cols;
int **temp = new int*[height];
for (int i = 0; i < height; i++) {
temp[i] = new int[width];
}
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
temp[i][j] = 0;
}
}
int filterHeight = 3;
int filterWidth = 3;
int newImageHeight = height - filterHeight + 1;
int newImageWidth = width - filterWidth + 1;
int i, j, h, w;
//convolution
for (i = 0; i < newImageHeight; i++) {
for (j = 0; j < newImageWidth; j++) {
for (h = i; h < i + filterHeight; h++) {
for (w = j; w < j + filterWidth; w++) {
temp[i][j] += filter[h - i][w - j] * (int)img.at<uchar>(h, w);
}
}
}
}
//find max and min
int max = 0;
int min = 100;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (temp[i][j] > max) {
max = temp[i][j];
}
if (temp[i][j] < min) {
min = temp[i][j];
}
}
}
//clamp 0 - 255
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
res.at<uchar>(i, j) = 0 + (temp[i][j] - min)*(255 - 0) / (max - min);
}
}
//empty the temp array
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
temp[i][j] = 0;
}
}
//img - res and store it in temp array
for (int y = 0; y < res.rows; y++) {
for (int x = 0; x < res.cols; x++) {
//int a = (int)img.at<uchar>(y, x) - (int)res.at<uchar>(y, x);
//cout << a << endl;
temp[y][x] = (int)img.at<uchar>(y, x) - (int)res.at<uchar>(y, x);
}
}
//find the new max and min
max = 0;
min = 100;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (temp[i][j] > max) {
max = temp[i][j];
}
if (temp[i][j] < min) {
min = temp[i][j];
}
}
}
//clamp it back to 0-255
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
res.at<uchar>(i, j) = 0 + (temp[i][j] - min)*(255 - 0) / (max - min);
temp[i][j] = (int)res.at<uchar>(i, j);
}
}
return res;
}
And here's the result
as you can see in my code above , i already normalize the pixel value to 0-255. i still don't know what went wrong here. Can anyone here explain why is that ?
The greyness is because, as Max suggested in his answer, you are scaling to the 0-255 range, not clamping (as your comments in the code suggest).
However, that is not all of the issues in your code. The output of the Laplace operator contains negative values. You nicely store these in an int. But then you scale and copy over to a char. Don't do that!
You need to add the result of the Laplace unchanged to your image. This way, some pixels in your image will become darker, and some lighter. This is what causes the edges to appear sharper.
Simply skip some of the loops in your code, and keep one that does temp = img - temp. That result you can freely scale or clamp to the output range and cast to char.
To clamp, simply set any pixel values below 0 to 0, and any above 255 to 255. Don't compute min/max and scale as you do, because there you reduce contrast and create the greyish wash over your image.
Your recent question is quite similar (though the problem in the code was different), read my answer there again, it suggests a way to further simplify your code so that img-Laplace becomes a single convolution.
The problem is that you are clamping and rescaling the image. Look at the bottom left border of the moon: There are very bright pixels next to very dark pixels, and then some gray pixels right besides the bright ones. Your sharpening filter will really spike on that bright border and increase the maximum. Similarly, the black pixels will be reduced even further.
You then determine minimum and maximum and rescale the entire image. This necessarily means the entire image will lose contrast when displayed in the previous gray scale, because your filter outputted pixel values above 255 and below 0.
Looks closely at the border of the moon in the output image:
There is a black halo (the new 0) and a bright, sharp edge (the new 255). (The browser image scaling made it less crisp in this screenshot, look at your original output). Everything else was squashed by the rescaling, so what was previous black (0) is now dark gray.

Alpha-trimmed filter troubles

I am trying to make an alphatrimmed filter in openCV library. My code is not working properly and the resultant image is not looking as image after filtering.
The filter should work in the following way.
Chossing some (array) of pixels in my example it is 9 pixels '3x3' window.
Ordering them in increasing way.
Cutting our 'array' both sides for alpha-2.
calculating arithmetic mean of remaining pixels and inserting them in proper place.
int alphatrimmed(Mat img, int alpha)
{
Mat img9 = img.clone();
const int start = alpha/2 ;
const int end = 9 - (alpha/2);
//going through whole image
for (int i = 1; i < img.rows - 1; i++)
{
for (int j = 1; j < img.cols - 1; j++)
{
uchar element[9];
Vec3b element3[9];
int k = 0;
int a = 0;
//selecting elements for window 3x3
for (int m = i -1; m < i + 2; m++)
{
for (int n = j - 1; n < j + 2; n++)
{
element3[a] = img.at<Vec3b>(m*img.cols + n);
a++;
for (int c = 0; c < img.channels(); c++)
{
element[k] += img.at<Vec3b>(m*img.cols + n)[c];
}
k++;
}
}
//comparing and sorting elements in window (uchar element [9])
for (int b = 0; b < end; b++)
{
int min = b;
for (int d = b + 1; d < 9; d++)
{
if (element[d] < element[min])
{
min = d;
const uchar temp = element[b];
element[b] = element[min];
element[min] = temp;
const Vec3b temporary = element3[b];
element3[b] = element3[min];
element3[min] = temporary;
}
}
}
// index in resultant image( after alpha-trimmed filter)
int result = (i - 1) * (img.cols - 2) + j - 1;
for (int l = start ; l < end; l++)
img9.at<Vec3b>(result) += element3[l];
img9.at<Vec3b>(result) /= (9 - alpha);
}
}
namedWindow("AlphaTrimmed Filter", WINDOW_AUTOSIZE);
imshow("AlphaTrimmed Filter", img9);
return 0;
}
Without actual data, it's somewhat of a guess, but an uchar can't hold the sum of 3 channels. It works modulo 256 (at least on any platform OpenCV supports).
The proper solution is std::sort with a proper comparator for your Vec3b :
void L1(Vec3b a, Vec3b b) { return a[0]+a[1]+a[2] < b[0]+b[1]+b[2]; }

From mathematic function to c++ code

I am trying to implement this F(S) function:
bellow is my code but is not working:
double EnergyFunction::evaluate(vector<short> field) {
double e = 0.0;
for (int k = 1; k < field.size() - 1; k++){
double c = 0.0;
for (int i = 1; i < field.size() - k; i++) {
c += field[i] * field[i + k];
}
e += pow(c, 2);
}
double f = pow(field.size(), 2) / ( 2 * e );
return f;
}
For example F(S) function should return value 8644 for vector:
1,1,1,-1,-1,-1,1,-1,1,1,-1,1,-1,1,-1,1,-1,-1,1,1,1,1,-1,-1,-1,1,1,1,1,-1,1,-1,1,1,-1,-1,1,1,1,1,-1,-1,-1,1,-1,-1,1,-1,-1,1,1,-1,1,-1,-1,1,1,-1,1,-1,1,-1,1,-1,1,-1,1,1,-1,-1,-1,-1,-1,-1,1,-1,1,1,1,-1,1,1,-1,1,1,-1,1,-1,1,1,1,-1,-1,1,1,-1,-1,1,1,1,1,1,1,1,1,-1,1,-1,1,-1,1,-1,-1,1,-1,-1,1,-1,-1,1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,1,-1,-1,1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,1,1,1,1,1,-1,1,-1,1,-1,1,1,1,1,1,1,-1,1,-1,-1,-1,1,-1,1,1,-1,-1,-1,-1,1,-1,-1,-1,1,1,-1,-1,1,1,1,-1,-1,1,1,1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,1,1,-1,-1,-1,-1,-1,1,-1,-1,-1,1,1,-1,1,1,-1,-1,-1,1,-1,-1,1,-1,-1,-1,1,1,1,-1,-1,-1,-1,1,1,1,-1,1,-1,-1,1,-1,1,1,-1,-1,-1,-1,1,-1,1,1,1,1,1,1,-1,1,1,1,-1,-1,-1,-1,1,-1,1,1,1,1,-1,1,1,1,1,1,-1,-1,-1,1,-1,-1,1,1,1,-1,1,1,1,-1,1,1
I need another par of eyes to look at my code because I am a bit lost here. :)
after refactoring:
double EnergyFunction::evaluate(vector<short> field) {
double e = 0.0;
int l = field.size()
for (int k = 1; k < l; k++){
double c = 0.0;
for (int i = 0, j = k; j < l; i++, j++) {
c += field[i] * field[j];
}
e += c*c;
}
return l*l / ( e+e );
}
explanation:
1. we need to iterate (L-1) times
2. we need to shift the base and offset indexes until we reach the last one
3. c*c and e+e are quicker and easier to read
You are mapping variables into different ranges using the same names, which is always going to be confusing. Better is to keep ranges and names the same as in the math, and only subtract one for 0-base indexes at indexing time. Also might as well use L explicitly:
int L = field.size();
for (int k = 1; k <= L-1; k++){
...
for (int i = 1; i <= L-k; i++) {
c += field[i -1] * field[i+k -1];
...

calculating euclidean distance for Luv values between 2 pixels

In opencv c++ I'm trying to figure out how to calculate the euclidean distance between point i,j and all points within a 3x3 kernel. This is to create a contrast map of saliency from the Luv color space. I've also tried the norm function to no avail. I'm very confused as to how to solve this problem and would appreciate some feedback.
Mat tmp1 = MeanShift_Luv.clone();
int big_theta = 3; // kernel size / neighborhood to perform convolution on
Mat gradient_1 = Mat::zeros(tmp1.rows, tmp1.cols, CV_64FC3);
for (int i = 0; i < tmp1.rows; i++){
for (int j = 0; j < tmp1.cols; j++){
double dist = 0;
for (int m = -big_theta / 2; m < big_theta / 2; m++){
for(int n = -big_theta /2; n < big_theta / 2; n++){
if (m == 0 || n == 0) continue;
if (i + m < 0 || i + m >= tmp1.rows) continue;
if (j + n < 0 || j + n >= tmp1.cols) continue;
/* unsure what to do at this part
Point a(i,j);
Point b(i+m, j+n);
*/
}
}
gradient_1.at<Vec3d>(i,j) = dist;
}

optimizing for loops in c++ code

Integer Range = 1;
for(Integer k = -Range; k <= Range; ++k)
{
for(Integer j = -Range; j <= Range; ++j)
{
for(Integer i = -Range; i <= Range; ++i)
{
Integer MCID = GetCellID(&CONSTANT_BOUNDINGBOX,CIDX +i, CIDY + j,CIDZ
+ k);
if(MCID < 0 || MCID >= c_CellNum)
{
continue;
}
unsigned int TriangleNum = c_daCell[MCID].m_TriangleNum;
for(unsigned int l = 0; l < TriangleNum; ++l)
{
TriangleID=c_daCell[MCID].m_TriangleID[l];
if( TriangleID >= 0 && TriangleID < c_TriangleNum && TriangleID
!= NearestID)// No need to calculate again for the same triangle
{
CDistance Distance ;
Distance.Magnitude = CalcDistance(&c_daTriangles[TriangleID], &TargetPosition,
&Distance.Direction);
if(Distance.Magnitude < NearestDistance.Magnitude)
{
NearestDistance = Distance;
NearestID = TriangleID;
}
}
}
}
}
}
}
c_daSTLDistance[ID] = NearestDistance;
c_daSTLID[ID] = NearestID;
GetCellID is the function to return the cellid in the variable CID with CIDX,CIDY,CIDZ with its position in the 3 axes
here the above code is a function to calculate the distance ,actually STL distance between a point and the triangles of the stl. This code runs fine however the problem is it is too slow as it has large number of loops within the code. Now my concern is to optimize the loop. Is there any technique of optimizing the loops within the code?