Reputation: 120
I am trying to blur an image without using opencv predefined functions like blur(). I am using standard average and not the weighted average. here is my code but the result is still the same with the input image. this is for 3x3.
IplImage* img = cvLoadImage(argv[1]);
IplImage* dst = cvCloneImage(img);
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
data = (uchar *)img->imageData;
height2 = dst->height; // row
width2 = dst->width; // col
step2 = dst->widthStep; // size of aligned image row in bytes
channels2 = dst->nChannels;
dstData = (uchar *)dst->imageData;
int total = 0;
//blur
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
for (x = 0; x <= 2; x++)
for (y = 0; y <= 2; y++)
total =(data[x-1,y-1]+data[x-1,y]+data[x-1,y+1]+
data[x,y-1]+data[x,y]+data[x,y+1]+
data[x+1,y-1]+data[x+1,y]+data[x+1,y+1])/9;
dstData[i,j] = total;
}
}
i think my problem is on this one
total =(data[x-1,y-1]+data[x-1,y]+data[x-1,y+1]+
data[x,y-1]+data[x,y]+data[x,y+1]+
data[x+1,y-1]+data[x+1,y]+data[x+1,y+1])/9;
dstData[i,j] = total;
what could be done?
Upvotes: 1
Views: 4880
Reputation: 5708
a complete program that shows how to do it. you have several errors, 1) incorrect pixel access(http://www.comp.leeds.ac.uk/vision/opencv/iplimage.html). 2) blur loop is wrong,you are always getting data from top left 3x3 corner. if pixel access is correct, you should get a constant image in dst.
another thing is you would also need to take care of channel information, the program bypass that by reading in a single channel image. otherwise you would need to do the blur for each channel
#include <opencv2/opencv.hpp>
int main(int argc, char* argv[])
{
IplImage* img = cvLoadImage("c:/data/2.jpg",0);
IplImage* dst = cvCloneImage(img);
int height,width,step,channels;
int height2,width2,step2,channels2;
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
uchar* data = (uchar *)img->imageData;
height2 = dst->height; // row
width2 = dst->width; // col
step2 = dst->widthStep; // size of aligned image row in bytes
channels2 = dst->nChannels;
uchar* dstData = (uchar *)dst->imageData;
int total = 0;
int i,j,x,y,tx,ty;
//blur
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
int ksize=3;
total=0;
for (x = -ksize/2; x <=ksize/2; x++)
for (y = -ksize/2; y <=ksize/2; y++)
{
tx=i+x;
ty=j+y;
if(tx>=0&&tx<height && ty>=0 && ty<width)
{
total+=data[tx*step+ty];
}
}
dstData[i*step+j] = total/ksize/ksize;
}
}
cvShowImage("img",img);
cvShowImage("dst",dst);
cvWaitKey(0);
}
Upvotes: 1
Reputation: 607
Assume assigning 0 to pixels out of range, the following code should be what you want. The core is my_average
function, it computes the average of the 3 * 3 window centered at i
and j
.
for (i = 0; i < height; i++)
for (j=0; j < width; j++)
dstData[i*width+j] = my_average(data, i, j, height, width);
double my_average(uchar * data, int y, int x, int height, int width) {
double sum = 0;
if(x-1 >= 0 && y-1 >= 0) {
sum += data[(y-1)*width + x-1];
}
if(x-1 >= 0) {
sum += data[y*width + x-1];
}
if(x-1 >= 0 && y+1 < height) {
sum += data[(y+1)*width + x-1];
}
if(y-1 >= 0) {
sum += data[(y-1)*width + x];
}
sum += data[y*width + x];
if(y+1 < height) {
sum += data[(y+1)*width + x];
}
if(x+1 < width && y-1 >= 0) {
sum += data[(y-1)*width + x+1];
}
if(x+1 < width) {
sum += data[y*width + x+1];
}
if(x+1 < width && y+1 < height) {
sum += data[(y+1)*width + x+1];
}
return sum/9;
}
Upvotes: 0