2014-02-20 15 views
3

我想獲得Android CvCameraViewFrame對象中的主色。我使用下面的OpenCV Android代碼來做到這一點。此代碼從OpenCV C++代碼轉換爲OpenCV Android代碼。在下面的代碼中,我遍歷相機框架中的所有像素,並找到每個像素的顏色,並將它們存儲在HashMap中以在循環結束時查找主色。爲了遍歷每個像素,大約需要30秒。這是我無法接受的。有人可以查看這些代碼,並指出我如何在相機框架中找到主色。在OpenCV中找到相機框架中的主色調Android

private String[] colors = {"cBLACK", "cWHITE", "cGREY", "cRED", "cORANGE", "cYELLOW", "cGREEN", "cAQUA", "cBLUE", "cPURPLE", "cPINK", "cRED"}; 

public Mat onCameraFrame(CvCameraViewFrame inputFrame) { 
     mRgba = inputFrame.rgba(); 

     if (mIsColorSelected) { 
      Imgproc.cvtColor(mRgba, mRgba, Imgproc.COLOR_BGR2HSV); 

      int h = mRgba.height();    // Pixel height 
      int w = mRgba.width();    // Pixel width 
      int rowSize = (int)mRgba.step1();  // Size of row in bytes, including extra padding 

      float initialConfidence = 1.0f; 

      Map<String, Integer> tallyColors = new HashMap<String, Integer>(); 

      byte[] pixelsTotal = new byte[h*rowSize]; 
      mRgba.get(0,0,pixelsTotal); 

      //This for loop takes about 30 seconds to process for my camera frame 
      for (int y=0; y<h; y++) { 
       for (int x=0; x<w; x++) { 
        // Get the HSV pixel components 

        int hVal = (int)pixelsTotal[(y*rowSize) + x + 0]; // Hue 
        int sVal = (int)pixelsTotal[(y*rowSize) + x + 1]; // Saturation 
        int vVal = (int)pixelsTotal[(y*rowSize) + x + 2]; // Value (Brightness) 


        // Determine what type of color the HSV pixel is. 
        String ctype = getPixelColorType(hVal, sVal, vVal); 
        // Keep count of these colors. 
        int totalNum = 0; 
        try{ 
         totalNum = tallyColors.get(ctype); 
        } catch(Exception ex){ 
         totalNum = 0; 
        } 
        totalNum++; 
        tallyColors.put(ctype, totalNum); 
       } 
      } 

      int tallyMaxIndex = 0; 
      int tallyMaxCount = -1; 
      int pixels = w * h; 
      for (int i=0; i<colors.length; i++) { 
       String v = colors[i]; 
       int pixCount; 
       try{ 
        pixCount = tallyColors.get(v); 
       } catch(Exception e){ 
        pixCount = 0; 
       } 
       Log.i(TAG, v + " - " + (pixCount*100/pixels) + "%, "); 
       if (pixCount > tallyMaxCount) { 
        tallyMaxCount = pixCount; 
        tallyMaxIndex = i; 
       } 
      } 
      float percentage = initialConfidence * (tallyMaxCount * 100/pixels); 
      Log.i(TAG, "Color of currency note: " + colors[tallyMaxIndex] + " (" + percentage + "% confidence)."); 

     } 

     return mRgba; 
    } 

    private String getPixelColorType(int H, int S, int V) 
    { 
     String color; 
     if (V < 75) 
      color = "cBLACK"; 
     else if (V > 190 && S < 27) 
      color = "cWHITE"; 
     else if (S < 53 && V < 185) 
      color = "cGREY"; 
     else { // Is a color 
      if (H < 14) 
       color = "cRED"; 
      else if (H < 25) 
       color = "cORANGE"; 
      else if (H < 34) 
       color = "cYELLOW"; 
      else if (H < 73) 
       color = "cGREEN"; 
      else if (H < 102) 
       color = "cAQUA"; 
      else if (H < 127) 
       color = "cBLUE"; 
      else if (H < 149) 
       color = "cPURPLE"; 
      else if (H < 175) 
       color = "cPINK"; 
      else // full circle 
       color = "cRED"; // back to Red 
     } 
     return color; 
    } 

非常感謝。

+0

輸出h,w和rowSize。獲得的結果是什麼? –

+0

我得到h = 480,w = 640,rowSize = 1920的輸出值而不調整圖像的大小,當我按照@dervish的建議調整圖像大小時,得到h = 100,w = 100,rowSize = 300的輸出值 –

回答

4

想想來調整圖片的大小,那麼你可以乘以同一尺度下的結果:

resize(larg_image, smallerImage , interpolation=cv.CV_INTER_CUBIC); 

或者, 您可以檢查these solutions:

+0

非常感謝。正如你所建議的那樣,我通過這種方式將相機框架的大小調整爲100x100像素大小的圖像。 'Size sz = new Size(100,100); Imgproc.resize(mRgba,mRgba,sz,0,0,Imgproc.INTER_CUBIC);'這真的改善了我的代碼性能。現在,在我提到的上面的代碼中,我還遇到了另一個問題,那就是大部分時間它都會將主色調變成黑色或灰色。我覺得我發現主色的方式存在一些問題。你能幫我解決這個問題嗎? –

+0

這是一個聰明的想法,但根據調整大小的方法,像素的顏色可能會稍微改變。這可能是也可能不是問題,這取決於人們需要得到的主導顏色的準確程度。 –

4

OpenCV的一個Histogram method它可用於計算的圖像色彩。計算直方圖畢竟你必須做的是選擇(C++)的一個具有最大個性化......

檢查這裏的教程:Histogram Calculation.

您也可能會在this stackoverflow answer這顯示了一個例子關於如何使用Android的直方圖功能Imgproc.calcHist()