Найти доминирующий цвет в кадре камеры в OpenCV Android

Я хочу получить доминирующий цвет в объекте Android CvCameraViewFrame. Я использую следующий код OpenCV Android, чтобы сделать это. Этот код преобразуется из кода OpenCV c ++ в код OpenCV Android. В следующем коде я перебираю все пиксели в кадре своей камеры, нахожу цвет каждого пикселя и сохраняю их в HashMap, чтобы найти доминирующий цвет в конце цикла. Чтобы пройти через каждый пиксель, требуется около 30 секунд. Это неприемлемо для меня. Может кто-нибудь просмотреть этот код и указать мне, как я могу найти доминирующий цвет в кадре камеры.

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;
}

Большое спасибо.

4

Решение

OpenCV имеет Метод гистограммы который считает все цвета изображения. После того, как гистограмма рассчитана, все, что вам нужно сделать, это выбрать ту, которая имеет наибольшее количество …

Проверьте здесь для учебника (C ++): Расчет гистограммы.

Вы могли бы также этот стекопоток ответ который показывает пример того, как использовать функцию гистограммы Android Imgproc.calcHist(),

5

Другие решения

Подумайте об изменении размера ваших изображений, тогда вы можете умножить результаты в том же масштабе:

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

Или же,
вы можете проверить эти решения:

4

Вы можете найти доминирующий цвет, используя метод кластеризации k-средних.
эта ссылка будет полезна.
https://www.youtube.com/watch?v=f54-x3PckH8

0