在 OpenCV Android 中的相机帧中查找主色

Find dominant color in a camera frame in OpenCV Android

本文关键字:查找 OpenCV Android 相机      更新时间:2023-10-16

我想在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;
    }

谢谢。

OpenCV有一个直方图方法,可以计算所有图像颜色。计算直方图后,您所要做的就是选择计数最多的一个......

在此处查看教程 (C++):直方图计算。

你也可以 这个堆栈溢出答案 它显示了如何使用Android的直方图函数的示例 Imgproc.calcHist() .

考虑调整图像大小,然后您可以将结果乘以相同的比例:

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

或您可以检查以下解决方案:

您可以使用

k 均值聚类方法找到主色。此链接将很有用。https://www.youtube.com/watch?v=f54-x3PckH8