Реализация среднего фильтра не работает в OpenCV, но работает в Java

Какая боль. В принципе, все, что я пытаюсь сделать, это реализовать простой фильтр размытия на изображении. Я использую то же изображение, которое является 24-битным растровым изображением (Lena512.bmp). Теперь дело в том, что реализация Java, которую я написал, работает, как и ожидалось. Однако реализация C, а не размывание региона, который я хочу, фактически темнеет в регионе и выглядит странно. Я не слишком уверен, что это связано с преобразованием RGB (BGR). Я могу получить определенный пиксель для цвета и прочитать тот же цвет назад.

Я хочу изучить материал об обработке изображений, а не полагаться на библиотеку OpenCV для всего, просто для захвата изображений с веб-камеры и с моего диска.

Это моя реализация Java, которая работает. Img содержит 24-бит lena512.bmp.

private void applyFilter()
{ 
 //Apply the filter 3 times
 for (int n = 0; n < 3; n++) {
 for (int y=100; y < 300; y++) {
 for (int x=100; x<300; x++) {
 int r = 0,g = 0,b = 0;
 for (int j = -1; j <= 1; j++) {
 for (int k=-1; k<=1; k++) {
 int pixel = img.getRGB(x + k, y + j);
 r += (new Color(pixel).getRed());
 g += (new Color(pixel).getGreen());
 b += (new Color(pixel).getBlue());
 }
 }
 r = r / 9; //Assume a 3x3 matrix, to average out.
 g = g / 9;
 b = b / 9;
 img.setRGB(x, y, new Color(r,g,b).getRGB());
 }
 }
 }
}

Моя реализация C выглядит так. Img содержит 24 бит lena512.bmp.

void applyAverage(IplImage *img)
{
 int x,y;
 int nx, ny;

 for ( y = 100; y < 400; y++) {
 for ( x = 100; x < 400; x++) {
 unsigned char r,g,b;
 for ( ny = -1; ny <= 1; ny++) {
 for ( nx = -1; nx <= 1; nx++) {
 getPixel(img,x + nx,y + ny,&r, &g, &b);
 r += r;
 g += g;
 b += b;
 }
 }
 r = r / 9;
 g = g / 9;
 b = b / 9;
 setPixel(img, x, y, &r, &g, &b);
 }
 }
}

В основном методе реализации C я загрузил изображение следующим образом:

IplImage *frame = cvLoadImage("lena512.bmp",1);

Мои getPixel и getPixel работают, поскольку я могу установить и получить их (я знаю, что порядок байтов RGB ---> BGR, что не является проблемой). Очевидно, я что-то пропустил.

Спасибо людям.

Я связал (моя репутация слишком низкая) картина проблемы. Слева - реализация Java, справа - OpenCV.

http://i176.photobucket.com/albums/w189/Phil128/Problem_zps431a4a4f.png

2 ответа

Посмотрите внимательно на этот фрагмент кода, который должен накапливать значения интенсивности:

getPixel(img,x + nx,y + ny,&r, &g, &b);
r += r;
...

getPixel сохраняет перезапись переменных аккумулятора r, g, b на каждой итерации. Это означает, что после запроса последнего пикселя области фильтра. r, g и b будут просто удерживать значения этого последнего пикселя. r += r и, в конечном счете, r = r/9 означают, что интенсивность каждого отфильтрованного пикселя в конце будет приблизительно равна двум девятым значениям интенсивности его нижнего правого соседа в оригинале. Следовательно, регион становится очень темным.

Попробуйте использовать отдельные переменные, чтобы получать значения интенсивности каждого пикселя в области фильтра, такие как curr_r, curr_g и curr_b:

int r = 0, g = 0, b = 0;
for ( ny = -1; ny <= 1; ny ++) {
 for ( nx = -1; nx <= 1; n x++) {
 int curr_r, curr_g, curr_b; 
 getPixel(img, x + nx, y + ny, & curr_r, & curr_g, &curr_b);
 r += curr_r; 
 g += curr_g;
 b += curr_b;
 }
}
r = r / 9;
g = g / 9;
b = b / 9;

Здесь getPixel поместит значения интенсивности в curr_r, например, тогда curr_r добавляется к накапливающей переменной r.

Еще одна вещь. Вы передаете адреса r, g и b в setPixel как в setPixel(img, x, y, & r, & g, & b); , Возможно, это правильный способ сделать это, но я предпочел бы, что setPixel примет значения, как в setPixel(img, x, y, r, g, b); , Было бы целесообразно дважды проверить объявление этой функции.


Критерий сортировки. Дурак я. Я использовал unsigned char вместо int. Что происходит, когда мне не хватает сна: -D.

licensed under cc by-sa 3.0 with attribution.