Помогите с фильтром Собеля

Мне нужно написать программу, которая бы обрабатывала изображение по фильтру Собеля(выделение границ на изображении). Вроде всё сделал по формулам, но у меня при обработке изображения выдаёт вот это. При применении фильтра Собеля на это же изображение в GIMP'е получается это. Если кто-нибудь занимается изображениями помогите пожалуйста. Эту же прогу делал со scanline вместо попиксельного обращения, результат такой же.
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include <tchar.h>
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
   int GX[3][3], GY[3][3], sumX = 0, sumY = 0, SUM = 0;
    Graphics::TBitmap *img = new Graphics::TBitmap;
    img->LoadFromFile("1.bmp");
 
   GX[3][3] = -1; GX[3][3] = 0; GX[3][3] = 1;
   GX[3][3] = -2; GX[3][3] = 0; GX[3][3] = 2;
   GX[3][3] = -1; GX[3][3] = 0; GX[3][3] = 1;
 
   GY[3][3] =  1; GY[3][3] = 2; GY[3][3] = 1;
   GY[3][3] =  0; GY[3][3] = 0; GY[3][3] = 0;
   GY[3][3] = -1; GY[3][3] = -2; GY[3][3] = -1;
 
    for (int Y = 0; Y < img->Height; Y++) {
        for (int X = 0; X < img->Width; X++) {
            sumX = 0;
            sumY = 0;
            if (Y == 0 || Y == img->Height)
                SUM = 0;
            else if (X == 0 || X == img->Width)
                SUM = 0;
            else {
                for (int I = -1; I <= 1; I++) {
                    for (int J = -1; J <= 1; J++) {
 
                        int piX = J + X;
                        int piY = I + Y;
 
                        COLORREF pixVal = img->Canvas->Pixels[piX][piY];
 
                        int R = GetRValue(pixVal);
                        int G = GetGValue(pixVal);
                        int B = GetBValue(pixVal);
 
                        int NC = (R + G + B) / 3;
 
                        sumX = sumX + (NC) * GX[J + 1][I + 1];
                        sumY = sumY + (NC) * GY[J + 1][I + 1];
                    }
                }
                SUM = sqrt(pow(sumX,2) + pow(sumY,2));
            }
            if (SUM > 255)
                SUM = 255;
            if (SUM < 0)
                SUM = 0;
            int newPixel = SUM;
            COLORREF newPixCol = RGB(newPixel, newPixel, newPixel);
            img->Canvas->Pixels[X][Y] = newPixCol;
        }
    }
    img->SaveToFile("2.bmp");
    return 0;
}
4 ответа

   
   GX[3][3] = -1; GX[3][3] = 0; GX[3][3] = 1;
   GX[3][3] = -2; GX[3][3] = 0; GX[3][3] = 2;
   GX[3][3] = -1; GX[3][3] = 0; GX[3][3] = 1;
 
   GY[3][3] =  1; GY[3][3] = 2; GY[3][3] = 1;
   GY[3][3] =  0; GY[3][3] = 0; GY[3][3] = 0;
   GY[3][3] = -1; GY[3][3] = -2; GY[3][3] = -1;
я плохо представляю что это, но думаю должно быть так:
   GX[0][0] = -1; GX[0][1] = 0; GX[0][2] = 1;
   GX[1][0] = -2; GX[1][1] = 0; GX[1][2] = 2;
   GX[2][0] = -1; GX[2][1] = 0; GX[2][2] = 1;
 
   GY[0][0] =  1; GY[0][1] = 2; GY[0][2] = 1;
   GY[1][0] =  0; GY[1][1] = 0; GY[1][2] = 0;
   GY[2][0] = -1; GY[2][1] = -2; GY[2][2] = -1;
да, так оно и есть. *почитал маны*


Спасибо за помощь! Действительно что-то я реально с массивами ступил жестоко. Теперь прога нормально работает даже с scanline. Выкладываю код, вдруг кому понадобится.
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include <tchar.h>
#pragma argsused
Graphics::TBitmap *Sobel(Graphics::TBitmap *image);
int _tmain(int argc, _TCHAR* argv[])
{
    Graphics::TBitmap *img = new Graphics::TBitmap;
    img->LoadFromFile("1.bmp");
    Sobel(img)->SaveToFile("2.bmp");
    return 0;
}
 
Graphics::TBitmap *Sobel(Graphics::TBitmap *img) {
    Graphics::TBitmap *returnImage = new Graphics::TBitmap;
    returnImage->SetSize(img->Width, img->Height);
    returnImage->PixelFormat = pf24bit;
    Byte *ptr, *ptrup, *ptrdown, *ptrres, *ptrcur;
    int sumX = 0, sumY = 0;
    short SUM = 0;
 
    int GX[3][3]={{-1, 0, 1},
                 {-2, 0, 2},
                 {-1, 0, 1}};
 
    int GY[3][3]={{ 1, 2, 1},
                 { 0, 0, 0},
                 {-1,-2,-1}};
 
    for (int Y = 1; Y < img->Height - 1; Y++) {
        ptrres = (Byte*)returnImage->ScanLine[Y];
        ptr = (Byte*)img->ScanLine[Y];
        ptrup = (Byte*)img->ScanLine[Y - 1];
        ptrdown = (Byte*)img->ScanLine[Y + 1];
        for (int X = 0; X < 3 * img->Width; X += 3) {
            if (Y - 1 == 0 || Y + 1 == img->Height - 1) SUM = 0;
            else if (X == 0 || X == img->Width - 3) SUM = 0;
            else {
                sumX = 0;
                sumY = 0;
                for (int I = -1; I <= 1; I++) {
                    for (int J = -1; J <= 1; J++) {
                        switch(I) {
                        case -1:ptrcur = ptrup; break;
                        case 0:ptrcur = ptr; break;
                        case 1:ptrcur = ptrdown; break;
                        }
                        int piX = 3 * J + X;
                        int NC = 0.299 * ptrcur[piX + 2] + 0.587 * ptrcur
                            [piX + 1] + 0.114 * ptrcur[piX];
                        sumX = sumX + NC * GX[I + 1][J + 1];
                        sumY = sumY + NC * GY[I + 1][J + 1];
                    }
                }
                SUM = abs(sumX) + abs(sumY);
                if (SUM > 255) SUM = 255;
                if (SUM < 0) SUM = 0;
            }
            SUM = 255 - abs(SUM);
            ptrres[X + 2] = SUM;
            ptrres[X + 1] = SUM;
            ptrres[X] = SUM;
        }
    }
    return returnImage;
}


Я в билдере запустил - программа не создает того, что надо. Только закрашивает в черный цвет 90% картинки.


А может у кого то есть этот же фильтр Собеля но ток для C#? Очень нужно