public void processImage(Mat imageToProcess) {
    try {
      final Mat processedImage = imageToProcess.clone();
      // red
      final Mat redUpper = new Mat();
      final Mat redLower = new Mat();
      Core.inRange(processedImage, new Scalar(170, 100, 20), new Scalar(180, 255, 255), redUpper);
      Core.inRange(processedImage, new Scalar(0, 100, 20), new Scalar(20, 255, 255), redLower);
      Core.bitwise_or(redLower, redUpper, processedImage);

      // refining the binary image
      Imgproc.erode(processedImage, processedImage, new Mat(), new Point(-1, -1), 1);
      Imgproc.dilate(processedImage, processedImage, new Mat(), new Point(-1, -1), 0);

      // create a clone for the processedImage to be used in finding contours
      final Mat clone = processedImage.clone();
      Imgproc.cvtColor(processedImage, processedImage, Imgproc.COLOR_GRAY2RGB);

      // finds list of contours and draw the biggest on the processedImage
      final Scalar color1 = new Scalar(0, 0, 255);
      final Scalar color2 = new Scalar(255, 255, 0);
      final Scalar color3 = new Scalar(255, 255, 255);
      final List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
      Imgproc.findContours(
          clone, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE);

      final List<MatOfPoint> contour = new ArrayList<MatOfPoint>(1);
      double maxArea = 0.0;
      for (int index = 0; index < contours.size(); index++) {
        double area = Imgproc.contourArea(contours.get(index));
        if (area > maxArea && area > 25 && Imgproc.boundingRect(contours.get(index)).y > 40) {
          maxArea = area;
          contour.add(0, contours.get(index));
        }
      }
      // finds bounding Rectangle and draws contours
      Rect boundingRect = new Rect();
      if (contour.size() > 0) {
        Imgproc.drawContours(processedImage, contour, -2, color1);
        boundingRect = Imgproc.boundingRect(contour.get(0));
        final double x = boundingRect.x;
        final double y = boundingRect.y;
        final double width = boundingRect.width;
        final double height = boundingRect.height;
        Core.rectangle(processedImage, new Point(x, y), new Point(x + width, y + height), color3);
      }
      // finding bounding Circle and draws it
      final Point center = new Point();
      final float[] radius = new float[1];
      if (contour.size() > 0) {
        final MatOfPoint2f contour2f = new MatOfPoint2f(contour.get(0).toArray());
        Imgproc.minEnclosingCircle(contour2f, center, radius);
        Core.circle(processedImage, center, (int) radius[0], color2);
      }

      final BallStruct redBallStruct = new BallStruct(boundingRect, center, (double) radius[0]);
      final BallTargeting ballTargeting = new BallTargeting(redBallStruct);

      synchronized (this) {
        distanceToRed = ballTargeting.getDistance();
        angleToRedInDegrees = ballTargeting.getAngle() * (180 / Math.PI);
        this.processedImage = processedImage;
      }
    } catch (Exception e) {

    }
  }
  public void process(Mat rgbaImage) {
    Mat pyrDownMat = new Mat();

    Imgproc.pyrDown(rgbaImage, pyrDownMat);
    Imgproc.pyrDown(pyrDownMat, pyrDownMat);

    Mat hsvMat = new Mat();
    Imgproc.cvtColor(pyrDownMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL);

    Mat Mask = new Mat();
    Core.inRange(hsvMat, mLowerBound, mUpperBound, Mask);
    Mat dilatedMask = new Mat();
    Imgproc.dilate(Mask, dilatedMask, new Mat());

    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
    Mat hierarchy = new Mat();

    Imgproc.findContours(
        dilatedMask, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

    blobCenters[0] = new Point();
    blobCenters[1] = new Point();

    if (contours.size() > 0) {

      // Find max contour area of the two biggest
      double[] maxArea = new double[2];
      maxArea[0] = 0; // biggest
      maxArea[1] = 0; // 2nd biggest
      Iterator<MatOfPoint> each = contours.iterator();
      int[] contourIndex = new int[2];
      contourIndex[0] = 0;
      contourIndex[1] = 0;
      int index = 0;
      while (each.hasNext()) {
        MatOfPoint wrapper = each.next();
        double area = Imgproc.contourArea(wrapper);
        if (area > maxArea[0]) { // area bigger than the maximum found
          maxArea[1] = maxArea[0];
          contourIndex[1] = contourIndex[0];
          maxArea[0] = area;
          contourIndex[0] = index;
        } else if (area > maxArea[1]) { // area bigger than the second maximum found
          maxArea[1] = area;
          contourIndex[1] = index;
        }
        index++;
      }

      //        // another possibility to iterate through contours
      //        for (index = 0; index < contours.size(); index++) {
      //            d = Imgproc.contourArea (contours.get(index));

      Log.d("index0", Integer.toString(contourIndex[0]));
      Log.d("index1", Integer.toString(contourIndex[1]));

      MatOfPoint2f mMOP2f1 = new MatOfPoint2f();
      float[] radius = new float[contours.size()];

      // contours is a List<MatOfPoint>
      // so contours.get(x) is a single MatOfPoint
      // but to use approxPolyDP we need to pass a MatOfPoint2f
      // so we need to do a conversion

      contours.get(contourIndex[0]).convertTo(mMOP2f1, CvType.CV_32FC2);
      // get the center of the bigger contour found
      Point tempCenter = new Point();
      Imgproc.minEnclosingCircle(mMOP2f1, tempCenter, radius);
      blobCenters[0].x = tempCenter.x;
      blobCenters[0].y = tempCenter.y;
      blobRadius[0] = radius[0];

      Log.d("center0.x", Double.toString(blobCenters[0].x));
      Log.d("center0.y", Double.toString(blobCenters[0].y));
      Log.d("radius0", Double.toString(blobRadius[0]));

      contours.get(contourIndex[1]).convertTo(mMOP2f1, CvType.CV_32FC2);
      Imgproc.minEnclosingCircle(mMOP2f1, tempCenter, radius);
      blobCenters[1].x = tempCenter.x;
      blobCenters[1].y = tempCenter.y;
      blobRadius[1] = radius[0];

      Log.d("center1.x", Double.toString(blobCenters[1].x));
      Log.d("center1.y", Double.toString(blobCenters[1].y));
      Log.d("radius1", Double.toString(blobRadius[1]));

      // Filter contours by area and resize to fit the original image size
      mContours.clear();
      each = contours.iterator();
      while (each.hasNext()) {
        MatOfPoint contour = each.next();
        if (Imgproc.contourArea(contour) > mMinContourArea * maxArea[1]) {
          Core.multiply(contour, new Scalar(4, 4), contour);
          mContours.add(contour);
        }
      }

    } else {

      blobCenters[0].x = 0;
      blobCenters[0].y = 0;
      blobCenters[1].x = 0;
      blobCenters[1].y = 0;
    }
  }