Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用OpenCV实现Java中的反投影_Java_Android_Opencv_Image Processing - Fatal编程技术网

用OpenCV实现Java中的反投影

用OpenCV实现Java中的反投影,java,android,opencv,image-processing,Java,Android,Opencv,Image Processing,我想用反投影检测图像中的特征 首先,我非常乐意计算单色小图像的直方图,然后将其应用于较大的图像。然后,我可以在上面构建更多。 有一个例子,我想用Java做类似的事情。 遗憾的是,OpenCV的Java接口没有很好的文档记录 下面是我到目前为止的代码,但它不起作用(显然,否则我不会寻求帮助)。 如果有人能帮助我让它工作起来或者为Java API找到一些好的文档,那就太好了 import java.util.ArrayList; import org.opencv.core.*; import or

我想用反投影检测图像中的特征

首先,我非常乐意计算单色小图像的直方图,然后将其应用于较大的图像。然后,我可以在上面构建更多。 有一个例子,我想用Java做类似的事情。 遗憾的是,OpenCV的Java接口没有很好的文档记录

下面是我到目前为止的代码,但它不起作用(显然,否则我不会寻求帮助)。 如果有人能帮助我让它工作起来或者为Java API找到一些好的文档,那就太好了

import java.util.ArrayList;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;

public class ColorHistogramDetector extends ColorThresholdDetector {
    //private cvHistogram histogram;
    //histogram resolution for hue and saturation
    static final int hbins = 30;//, sbins = 32;

    public synchronized Mat detect(Mat inputFrame) {
        Mat calcFrame = new Mat();
        Imgproc.cvtColor(inputFrame, calcFrame, Imgproc.COLOR_RGB2HSV);

        Mat hue = calcFrame;
        ArrayList<Mat> dst = new ArrayList<Mat>();
        dst.add(hue);

        //create single color image
        Mat fillImg = new Mat(16, 16, CvType.CV_8UC3);
        fillImg.setTo(hsvColor);

        MatOfInt histSize=new MatOfInt(hbins,hbins);

        // hue varies from 0 to 179, see cvtColor
        // saturation varies from 0 (black-gray-white) to
        // 255 (pure spectrum color)
        MatOfFloat ranges = new MatOfFloat( 0,180,0,256 );

        Mat hist = new Mat();

        // we compute the histogram from the 0-th and 1-st channels
        MatOfInt channels = new MatOfInt(0, 1);

        ArrayList<Mat> fillImgs=new ArrayList<Mat>();
        fillImgs.add(fillImg);
        Imgproc.calcHist(fillImgs, channels, new Mat(), hist, histSize, ranges);

        outputFrame = new Mat();

        Imgproc.calcBackProject(dst, channels, hist, calcFrame, ranges, 1);

        int w = inputFrame.cols(); int h = inputFrame.rows();
        int bin_w = (int) Math.round( (double) w / hbins );
        Mat histImg = new Mat( w, h, CvType.CV_8UC3 );

        for( int i = 0; i < hbins; i ++ ) { 
           Core.rectangle( histImg, new Point( i*bin_w, h ), 
                           new Point( (i+1)*bin_w, 
                           h - Math.round( hist.get(0, i)[0]*h/255.0 ) ), 
                           new Scalar( 0, 0, 255 ), -1 ); 
        }

        hist.release();
        fillImg.release();

        Imgproc.cvtColor(histImg, calcFrame, Imgproc.COLOR_RGB2HSV);

        return calcFrame;
    }
}
import java.util.ArrayList;
导入org.opencv.core.*;
导入org.opencv.imgproc.imgproc;
公共类ColorHistoryGramDetector扩展ColorThresholdDetector{
//私有直方图;
//色调和饱和度的直方图分辨率
静态最终整数hbins=30;/,sbins=32;
公共同步Mat检测(Mat输入帧){
Mat calcFrame=新Mat();
Imgproc.cvtColor(输入框、计算框、Imgproc.COLOR_RGB2HSV);
Mat色调=calcFrame;
ArrayList dst=新的ArrayList();
添加(色调);
//创建单色图像
材料填充=新材料(16,16,CvType.CV_8UC3);
填充设置为(hsvColor);
MatOfInt histSize=新的MatOfInt(hbins,hbins);
//色调从0到179不等,请参见CVT颜色
//饱和度从0(黑-灰-白)到
//255(纯光谱颜色)
MatOfFloat范围=新的MatOfFloat(0180,0256);
Mat hist=新Mat();
//我们从第0和第1通道计算直方图
MatOfInt通道=新的MatOfInt(0,1);
ArrayList fillImgs=新的ArrayList();
fillImgs.add(fillImgs);
Imgproc.calcHist(fillImgs、channels、new Mat()、hist、histSize、ranges);
outputFrame=新垫();
Imgproc.calcBackProject(dst、频道、历史、calcFrame、范围,1);
int w=inputFrame.cols();int h=inputFrame.rows();
int bin_w=(int)数学四舍五入((双)w/hbins);
Mat histImg=新Mat(w、h、CvType.CV_8UC3);
对于(int i=0;i
使用(openCV的java接口)。它使用了与openCV相同的方法约定,并且有很多示例可以使用它。

代码中有几点看起来很奇怪,因此我建议您首先仔细阅读教程,然后将其更改为您的用例

您似乎与下面的教程非常接近,但看起来您正在对单色图像应用
calcHist
。我看不出这有多有用,它通常应该是带有一些对象的HSV图像。此外,您还缺少
规范化
步骤

为了帮助您,我将其转换为OpenCV4Android 2.4.8

虽然您使用的是Java而不是Android,但API完全相同,只有样板输入/输出处理不同。

对原始教程进行了一些非常小的更改,使其更适用于Android,例如:

  • 它处理实时摄像机图像,而不是静态图像
  • 使用触摸事件替换鼠标单击
  • 反投影的输出显示在覆盖相机馈送的左上角
  • 增加了高斯模糊作为降噪

我还没有彻底测试所有步骤,但最终结果看起来还不错

注意:目前,您需要触摸屏幕一次以初始化反投影

以下是大部分内容,您可以找到缺少的内容:

private int outputWidth=300;
私有int outputhweight=200;
私人Mat mOutputROI;
私有布尔值bpUpdated=false;
私人Mat mRgba;
私人Mat mHSV;
私人垫面罩;
私人int lo=20;
私人int up=20;
开始时的公共空隙(整数宽度、整数高度){
mRgba=新垫(高度、宽度、CvType.CV_8UC3);
mHSV=新材料();
mIntermediateMat=新材料();
mGray=新垫(高度、宽度、CvType.CV_8UC1);
mOutputROI=新垫(输出高度,输出宽度,CvType.CV_8UC1);
mBitmap=Bitmap.createBitmap(宽度、高度、Bitmap.Config.ARGB_8888);
}
CameraFrame上的公用Mat(CvCameraViewFrame输入框){
Mat mCamera=inputFrame.rgba();
Imgproc.cvtColor(mCamera、mRgba、Imgproc.COLOR_RGBA2RGB);
Mat mOutputROI=mCamera.submat(0,输出宽度,0,输出宽度);
//添加以消除一些噪音:
GaussianBlur(mRgba,mRgba,新大小(5,5),0,Imgproc.BORDER_默认值);
Imgproc.CVT颜色(mRgba、mHSV、Imgproc.COLOR_RGB2HSV_FULL);
if(掩码!=null){
如果(bpUpdated==false){
mGray=histAndBackproj();
}否则{
bpUpdated=false;
}
调整Imgproc.resize(mGray、mIntermediateMat、mOutputROI.size()、0、0、Imgproc.INTER_LINEAR);
Imgproc.cvt颜色(mIntermediateMat、mOutputROI、Imgproc.COLOR_Gray 2bGra);
}
返回mCamera;
}
公共布尔onTouch(视图arg0,运动事件arg1){
点种子=getImageCoordinates(mRgba,arg1.getX(),arg1.getY());
int newMaskVal=255;
标量newVal=新标量(120120120);
int连接性=8;

int flags=connectivity+(newMaskVal它在哪里不工作?您是否收到错误,或者结果与您预期的不同?您似乎没有
normalize(…)
介于
calcHist
calcBackProject
之间。
hist
l的内容如何
private int outputWidth=300;
private int outputHeight=200;
private Mat mOutputROI;

private boolean bpUpdated = false;

private Mat mRgba;
private Mat mHSV;
private Mat mask;

private int lo = 20; 
private int up = 20;

public void onCameraViewStarted(int width, int height) {

    mRgba = new Mat(height, width, CvType.CV_8UC3);
    mHSV = new Mat();
    mIntermediateMat = new Mat();
    mGray = new Mat(height, width, CvType.CV_8UC1);
    mOutputROI = new Mat(outputHeight, outputWidth, CvType.CV_8UC1);

    mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);        
}

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

    Imgproc.cvtColor(mCamera, mRgba, Imgproc.COLOR_RGBA2RGB);

    Mat mOutputROI = mCamera.submat(0, outputHeight, 0, outputWidth);

    //Addition to remove some noise:
    Imgproc.GaussianBlur(mRgba, mRgba, new Size(5, 5), 0, Imgproc.BORDER_DEFAULT);

    Imgproc.cvtColor(mRgba, mHSV, Imgproc.COLOR_RGB2HSV_FULL);

    if(mask!=null){
        if(bpUpdated==false){
            mGray = histAndBackproj();
        } else {
            bpUpdated = false;
        }

        Imgproc.resize(mGray, mIntermediateMat, mOutputROI.size(), 0, 0, Imgproc.INTER_LINEAR);
        Imgproc.cvtColor(mIntermediateMat, mOutputROI, Imgproc.COLOR_GRAY2BGRA);
    }

    return mCamera;
}

public boolean onTouch(View arg0, MotionEvent arg1) {       
    Point seed = getImageCoordinates(mRgba, arg1.getX(), arg1.getY());

    int newMaskVal = 255;
    Scalar newVal = new Scalar( 120, 120, 120 );

    int connectivity = 8;
    int flags = connectivity + (newMaskVal << 8 ) + Imgproc.FLOODFILL_FIXED_RANGE + Imgproc.FLOODFILL_MASK_ONLY;

    Mat mask2 = Mat.zeros( mRgba.rows() + 2, mRgba.cols() + 2, CvType.CV_8UC1 );

    Rect rect = null;
    Imgproc.floodFill( mRgba, mask2, seed, newVal, rect, new Scalar( lo, lo, lo ), new Scalar( up, up, up), flags );

    // C++: 
    // mask = mask2( new Range( 1, mask2.rows() - 1 ), new Range( 1, mask2.cols() - 1 ) );
    mask = mask2.submat(new Range( 1, mask2.rows() - 1 ), new Range( 1, mask2.cols() - 1 ));

    mGray = histAndBackproj();
    bpUpdated = true;           

    return true;
}

  private Mat histAndBackproj() {
    Mat hist = new Mat();
    int h_bins = 30; 
    int s_bins = 32;

    // C++:
    //int histSize[] = { h_bins, s_bins };
    MatOfInt mHistSize = new MatOfInt (h_bins, s_bins);

    // C++:
    //float h_range[] = { 0, 179 };
    //float s_range[] = { 0, 255 };     
    //const float* ranges[] = { h_range, s_range };     
    //int channels[] = { 0, 1 };

    MatOfFloat mRanges = new MatOfFloat(0, 179, 0, 255);
    MatOfInt mChannels = new MatOfInt(0, 1);

    // C++:
    // calcHist( &hsv, 1, channels, mask, hist, 2, histSize, ranges, true, false );

    boolean accumulate = false;
    Imgproc.calcHist(Arrays.asList(mHSV), mChannels, mask, hist, mHistSize, mRanges, accumulate);

    // C++:
    // normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );        
    Core.normalize(hist, hist, 0, 255, Core.NORM_MINMAX, -1, new Mat());

    // C++:
    // calcBackProject( &hsv, 1, channels, hist, backproj, ranges, 1, true );        
    Mat backproj = new Mat();
    Imgproc.calcBackProject(Arrays.asList(mHSV), mChannels, hist, backproj, mRanges, 1);

    return backproj;
}


/**
 * Method to scale screen coordinates to image coordinates, 
 * as they have different resolutions.
 * 
 * x - width; y - height; 
 * Nexus 4: xMax = 1196; yMax = 768
 * 
 * @param displayX
 * @param displayY
 * @return
 */
private Point getImageCoordinates(Mat image, float displayX, float displayY){
    Display display = getWindowManager().getDefaultDisplay();       
    android.graphics.Point outSize = new android.graphics.Point();
    display.getSize(outSize);

    float xScale = outSize.x / (float) image.width();
    float yScale = outSize.y / (float) image.height();                  

    return new Point(displayX/xScale, displayY/yScale);
}