1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2012 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// Extract histogram from image. 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterpacks.histogram; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Filter; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Frame; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameBuffer2D; 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameType; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.InputPort; 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.MffContext; 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.OutputPort; 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Signature; 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer; 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteOrder; 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.FloatBuffer; 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * ChromaHistogramFilter takes in an image in HSVA format and computes a 2-D histogram with a 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 2 dimensional chroma histogram based on hue (column) and saturation (row) at the top and 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * a 1-D value histogram in the last row. The number of bin in the value histogram equals to 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * the number of bins in hue. 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic final class NewChromaHistogramFilter extends Filter { 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mHueBins = 6; 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mSaturationBins = 3; 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mValueBins; 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mSaturationThreshold = 26; // 255 * 0.1 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mValueThreshold = 51; // 255 * 0.2 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public NewChromaHistogramFilter(MffContext context, String name) { 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks super(context, name); 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Signature getSignature() { 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameType imageIn = FrameType.image2D(FrameType.ELEMENT_RGBA8888, FrameType.READ_CPU); 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameType dataOut = FrameType.buffer2D(FrameType.ELEMENT_FLOAT32); 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Signature() 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("image", Signature.PORT_REQUIRED, imageIn) 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("huebins", Signature.PORT_OPTIONAL, FrameType.single(int.class)) 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("saturationbins", Signature.PORT_OPTIONAL, FrameType.single(int.class)) 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("saturationthreshold", Signature.PORT_OPTIONAL, 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameType.single(int.class)) 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("valuethreshold", Signature.PORT_OPTIONAL, FrameType.single(int.class)) 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addOutputPort("histogram", Signature.PORT_REQUIRED, dataOut) 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .disallowOtherPorts(); 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onInputPortOpen(InputPort port) { 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (port.getName().equals("huebins")) { 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks port.bindToFieldNamed("mHueBins"); 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks port.setAutoPullEnabled(true); 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (port.getName().equals("saturationbins")) { 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks port.bindToFieldNamed("mSaturationBins"); 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks port.setAutoPullEnabled(true); 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (port.getName().equals("saturationthreshold")) { 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks port.bindToFieldNamed("mSaturationThreshold"); 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks port.setAutoPullEnabled(true); 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (port.getName().equals("valuethreshold")) { 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks port.bindToFieldNamed("mValueThreshold"); 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks port.setAutoPullEnabled(true); 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected void onProcess() { 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameBuffer2D imageFrame = getConnectedInputPort("image").pullFrame().asFrameImage2D(); 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks OutputPort outPort = getConnectedOutputPort("histogram"); 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mValueBins = mHueBins; 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] outDims = new int[] {mHueBins, mSaturationBins + 1}; 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameBuffer2D histogramFrame = outPort.fetchAvailableFrame(outDims).asFrameBuffer2D(); 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ByteBuffer imageBuffer = imageFrame.lockBytes(Frame.MODE_READ); 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ByteBuffer histogramBuffer = histogramFrame.lockBytes(Frame.MODE_READ); 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks histogramBuffer.order(ByteOrder.nativeOrder()); 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FloatBuffer floatHistogram = histogramBuffer.asFloatBuffer(); 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Run native method 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks extractChromaHistogram(imageBuffer, floatHistogram, mHueBins, mSaturationBins, mValueBins, 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSaturationThreshold, mValueThreshold); 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks imageFrame.unlock(); 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks histogramFrame.unlock(); 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outPort.pushFrame(histogramFrame); 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static native void extractChromaHistogram(ByteBuffer imageBuffer, 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FloatBuffer histogramBuffer, int hueBins, int saturationBins, int valueBins, 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int saturationThreshold, int valueThreshold); 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks static { 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks System.loadLibrary("smartcamera_jni"); 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 118