package resa.evaluation.topology.vld;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.opencv_core.*;
import org.bytedeco.javacpp.opencv_features2d.KeyPoint;
import org.bytedeco.javacpp.opencv_nonfree.SIFT;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_highgui.cvDecodeImage;
import static resa.evaluation.topology.vld.Constant.*;
/**
* Created by ding on 14-7-3.
*/
public class FeatureExtracter extends BaseRichBolt {
private SIFT sift;
private double[] buf;
private OutputCollector collector;
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
sift = new SIFT(500, 3, 0.05, 12, 1.6);
buf = new double[128];
this.collector = collector;
}
@Override
public void execute(Tuple input) {
byte[] imgBytes = (byte[]) input.getValueByField(FIELD_IMG_BYTES);
IplImage image = cvDecodeImage(cvMat(1, imgBytes.length, CV_8UC1, new BytePointer(imgBytes)));
KeyPoint points = new KeyPoint();
Mat featureDesc = new Mat();
Mat matImg = new Mat(image);
sift.detect(matImg, points);
sift.compute(matImg, points, featureDesc);
try {
cvReleaseImage(image);
} catch (Exception e) {
}
int rows = featureDesc.rows();
List<byte[]> selected = new ArrayList<>(rows);
for (int i = 0; i < rows; i++) {
featureDesc.rows(i).asCvMat().get(buf);
// compress data
byte[] siftFeat = new byte[buf.length];
for (int j = 0; j < buf.length; j++) {
siftFeat[j] = (byte) (((int) buf[j]) & 0xFF);
}
selected.add(siftFeat);
}
String frameId = input.getStringByField(FIELD_FRAME_ID);
collector.emit(STREAM_FEATURE_DESC, input, new Values(frameId, selected));
collector.emit(STREAM_FEATURE_COUNT, input, new Values(frameId, selected.size()));
collector.ack(input);
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declareStream(STREAM_FEATURE_DESC, new Fields(FIELD_FRAME_ID, FIELD_FEATURE_DESC));
declarer.declareStream(STREAM_FEATURE_COUNT, new Fields(FIELD_FRAME_ID, FIELD_FEATURE_CNT));
}
}