2016-08-02 106 views
3

我正在使用Sobel掩碼進行邊緣檢測而不使用任何特殊的庫。我想要得到的輸出是一個512x512矩陣的文本文件,其值在0到1之間。 我已經通過放置較小的值(如50而不是'ROW-2'和'COL-2')來檢查代碼的工作情況, 。 但是,如果我把它們放回去,代碼將永遠運行。我不明白爲什麼我的C++代碼運行速度很慢

常數的值是:

const int ROW = 512; 
const int COL = 512; 
const double Gx [3][3] = { {-1.0,0.0,1.0},{-2.0,0.0,2.0},{-1.0,0.0,1.0}}; 
const double Gy [3][3] = { {1.0,2.0,1.0},{0.0,0.0,0.0},{-1.0,-2.0,-1.0}}; 

這是主要的功能:

int main() 

{ 
    double NewImage[ROW][COL] = {0};  

    for (int i = 0; i < ROW; i++) 
    { 
     for (int j = 0; j < COL; j++) 
     { 
      NewImage[i][j] = 0; 
     } 
    } 

    for (int i = 0; i < ROW-2; i++) 
    { 
     for (int j = 0; j < COL-2; j++) 
     { 

      NewImage[i+1][j+1] = SobelConvolution(i,j); 
     } 
    } 

    ofstream newImage; 
    string filename; 
    filename = "output image.txt"; 

    newImage.open (filename.c_str()); 

    for(int rows = 0; rows < ROW; rows++) 
    { 
     for(int cols = 0; cols < COL; cols++) 
     { 
      newImage << NewImage[ROW][COL] <<" "; 
     } 
     newImage << endl; 
    } 

    newImage.close(); 

    return 0; 
} 

這是函數SobelConvolution:

double SobelConvolution(int row, int col) 
{ 
    double convX; 
    double convY; 
    double conv; 

    convX = ImageReader(row,col)*Gx[2][2] 
      + ImageReader(row,col+1)*Gx[2][1] 
      + ImageReader(row,col+2)*Gx[2][0] 
      + ImageReader(row+1,col)*Gx[1][2] 
      + ImageReader(row+1,col+1)*Gx[1][1] 
      + ImageReader(row+1,col+2)*Gx[1][0] 
      + ImageReader(row+2,col)*Gx[0][2] 
      + ImageReader(row+2,col+1)*Gx[0][1] 
      + ImageReader(row+2,col+2)*Gx[0][0]; 

    convY = ImageReader(row,col)*Gy[2][2] 
      + ImageReader(row,col+1)*Gy[2][1] 
      + ImageReader(row,col+2)*Gy[2][0] 
      + ImageReader(row+1,col)*Gy[1][2] 
      + ImageReader(row+1,col+1)*Gy[1][1] 
      + ImageReader(row+1,col+2)*Gy[1][0] 
      + ImageReader(row+2,col)*Gy[0][2] 
      + ImageReader(row+2,col+1)*Gy[0][1] 
      + ImageReader(row+2,col+2)*Gy[0][0]; 

    conv = sqrt((convX*convX) + (convY*convY)); 


    return conv; 
} 

這是函數的ImageReader:

double ImageReader(int r, int c) 
{ 
    double OrigImage[ROW][COL]; 

    ifstream defaultImage ("image.txt"); 

    if (defaultImage.good()) 
    { 
     for (int i = 0; i < ROW; i++) 
     { 
      for (int j = 0; j < COL; j++) 
      { 
       defaultImage >> OrigImage[i][j]; 
      } 
     } 
    } 
    return OrigImage [r][c]; 
} 

任何提示或建議?提前致謝!

+0

是否故意忽略'NewImage'的第一個和最後一個值(只留下它們到'0')? – Rakete1111

+0

是的。我認爲這樣做不會太複雜,不用擔心邊緣的值。這就是爲什麼程序導致問題的原因嗎? –

+0

不能:)有太多不必要的循環。 ;) – Rakete1111

回答

2

您是否真的打算單次打開18次圖像文件並讀取每行和每列的所有數據,以便返回單個行和列18次?爲什麼不一次讀取圖像文件並將圖像數據數組傳遞給函數?

+0

噢,我只是把它當作一種價值而已,忘了我實際上是在每次打開整個圖像文件時都這樣做。謝謝! –

+0

@RyanKim你每次都在遍歷整個數組:) – Rakete1111

4

這裏有一些注意事項:

  • ImageReader

    返回數組中只有一個值,無需通過整個陣列閱讀每時候,你只需要一個單一的值。在我看來,這個功能是多餘的。

  • SobelConvolution

    此功能是好的,但有一個不必要的變量 - conv

  • main

    我不知道爲什麼你的NewImage每個值初始化爲0,當他們已經0也實際上並不需要NewImage

這裏就是我會寫(與廣泛評論):

double SobelConvolution(int row, int col) 
{ 
    //ImageReader has been removed, it was unnecessary. The code has been moved here 
    double oldImage[ROW][COL]; 
    std::ifstream defaultImage{ "image.txt" }; 

    //Error handling if file doesn't exist - consider doing something else :) 
    if (!defaultImage.is_open()) 
     return 0; 

    //Initialize array 
    for (int i = 0; i < ROW; ++i) 
     for (int j = 0; j < COL; ++j) 
      defaultImage >> oldImage[i][j]; 

    //You should always declare variables where they are first used, this 
    //reduces the possibility of errors 
    //We can just access the array directly 
    double convX = oldImage[row][col] * Gx[2][2] 
     + oldImage[row][col + 1] * Gx[2][1] 
     + oldImage[row][col + 2] * Gx[2][0] 
     + oldImage[row + 1][col] * Gx[1][2] 
     + oldImage[row + 1][col + 1] * Gx[1][1] 
     + oldImage[row + 1][col + 2] * Gx[1][0] 
     + oldImage[row + 2][col] * Gx[0][2] 
     + oldImage[row + 2][col + 1] * Gx[0][1] 
     + oldImage[row + 2][col + 2] * Gx[0][0]; 

    double convY = oldImage[row][col] * Gy[2][2] 
     + oldImage[row][col + 1] * Gy[2][1] 
     + oldImage[row][col + 2] * Gy[2][0] 
     + oldImage[row + 1][col] * Gy[1][2] 
     + oldImage[row + 1][col + 1] * Gy[1][1] 
     + oldImage[row + 1][col + 2] * Gy[1][0] 
     + oldImage[row + 2][col] * Gy[0][2] 
     + oldImage[row + 2][col + 1] *Gy[0][1] 
     + oldImage[row + 2][col + 2]*Gy[0][0]; 

    //No need to create a separate variable just to return it 
    return sqrt((convX*convX) + (convY*convY)); 
} 


int main() 
{ 
    //= {} Initializes every element to 0, you don't need to do it :) Just so you know :) 
    //Note that it crashes here, because my stack size was too small, 
    //maybe consider using a dynamic array (512 * 512 is pretty big) :) 
    //double NewImage[ROW][COL] = {}; 
    //The array is not really needed, see below 

    std::string filename = "oimage.txt"; 
    std::ofstream newImage{ filename }; 

    //No need to create another array just to output it again, 
    //Just output the calculated values - this doesn't ignore the first/last values 
    for (int rows = 0; rows < ROW; rows++) 
    { 
     for (int cols = 0; cols < COL; cols++) 
      newImage << SobelConvolution(rows, cols) << " "; 
     newImage << '\n'; //std::endl flushes the stream, while \n does not - it is faster :) 
    } 

    newImage.close(); 

    return 0; 
} 
+0

我花了一點時間來看看你的評論。謝謝!它真的幫了我很多。我並不完全確定如何以這種方式聲明數組,所以這讓我放了更多變量來澄清,這使得它過於冗餘。 –

+0

@RyanKim歡迎您,如果您還有其他問題,請提問:) – Rakete1111

2

你在做什麼不只是一點點效率低下,這是-sorry-完全瘋了。

對於圖像的每個像素,您調用SobelConvolution,然後調用ImageReader 18次(其中6個沒用,因爲對應的係數爲零)。但可怕的是,ImageReader每次都會從文本文件中讀取完整的圖像,只需簡單的數組查找即可。

因此,您總共執行4718592個文件流打開/關閉和1236950581248值讀取文件,其中只有1個打開/關閉和262144讀取就足夠了。 (不要指望單個讀取比直接訪問更昂貴)。完整的運行可以持續兩個小時或更長時間。

相關問題