title: OpenCV: Detect color and draw line on color
body: <p>My application is going to calculate the bounce height of the battery, I intend to use the blue strip to define the "base" in which i use to calculate the number of pixels away it is from the battery.</p>
  
  <p>How do i detect that blue color and draw a line at the base of the blue strip of paper such that the line drawn could be used for pixel distance calculation?</p>
  
  <p>I'm aware that opencv has a blob detection application that draws contours around a color that was selected, but what I need is the application to automatically detect the color &amp; give me it's co-ordinate such that i can apply </p>
  
  <pre><code>canvas.drawLine(0, 0, 20, 20, p);
  </code></pre>
  
  <p>to draw the line</p>
  
  <p>Note: the detection &amp; line drawing is done on an bitmap image extracted from a video.</p>
  
  <p><a href="https://i.stack.imgur.com/pi25s.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/pi25s.jpg" alt="enter image description here"></a></p>
  
  <p><strong>EDIT:</strong>
  When i tested it out, it doesnt detect the blue color. i even tested it out on pictures that has blue and green colored paper, but the output dint detect blue...</p>
  
  <p>Here's my pictures:
  <a href="https://i.stack.imgur.com/SY9s2.png" rel="nofollow noreferrer">Output<img src="https://i.stack.imgur.com/SY9s2.png" alt="output"></a>
  <a href="https://i.stack.imgur.com/TxHeh.jpg" rel="nofollow noreferrer">Input<img src="https://i.stack.imgur.com/TxHeh.jpg" alt="input"></a>
  Here's my current code:</p>
  
  <pre><code>Mat hsvMat = new Mat();
              //Mat black_hue_range = new Mat();
              //Core.inRange(hsvMat, new Scalar(0, 0, 0), new Scalar(180, 255, 30, 0), black_hue_range);
              Mat blue_hue = new Mat();
              Scalar lower_blue = new Scalar(110,50,50);
              Scalar upper_blue = new Scalar(130,255,255);
  
              //Convert BGR to HSV
              Imgproc.cvtColor(srcMat, hsvMat, Imgproc.COLOR_BGR2HSV);
  
              //Threshold the HSV image to get only blue colors
              Core.inRange(hsvMat, lower_blue, upper_blue, blue_hue); // hue == a colour or shade
              Mat tempMat22 = new Mat();
              Core.bitwise_and(hsvMat,hsvMat,tempMat22,blue_hue);
              Utils.matToBitmap(tempMat22, b);
  
              //Bitmap mutableBitmap = b.copy(Bitmap.Config.ARGB_8888, true);
              imgR.setImageBitmap(b);
  </code></pre>
  
  <p><strong>EDIT:</strong></p>
  
  <p>The following code returned three values which i assumed was <code>H = data[0], S data[1], V = data[2]</code>
  Now that i have the HSV value how do i get the upper and lower limit? The answer given by Alexander Reynolds <a href="https://stackoverflow.com/questions/44896166/converting-a-single-bgr-color-with-cvtcolor-and-using-the-result-to-extract-that/44896475#44896475">here</a> seems to be for RGB and not HSV. <strong>Note:</strong> The color pixel im reading now is Green, not blue anymore.</p>
  
  <blockquote>
    <p>E/data: H:90.0  S:113.0  V:144.0</p>
  </blockquote>
  
  <pre><code>if (getIntent().hasExtra("byteArray")) {
  
              bitmap = BitmapFactory.decodeByteArray(getIntent().getByteArrayExtra("byteArray"), 0, getIntent().getByteArrayExtra("byteArray").length);
  
              int width= bitmap.getWidth();
              int height=bitmap.getHeight();
  
              int centerX=width/2;
              int centerY=height/2;
              srcMat = new Mat();
              Utils.bitmapToMat(bitmap, srcMat);
              Imgproc.cvtColor(srcMat, srcMat, Imgproc.COLOR_BGR2HSV);
              srcMat.convertTo(srcMat, CvType.CV_64FC3); //http://answers.opencv.org/question/14961/using-get-and-put-to-access-pixel-values-in-java/
              double[] data = srcMat.get(centerX, centerY);
              Log.e("data", String.valueOf("H:"+data[0]+" S:"+data[1]+" V:"+data[2]));
              Log.e("dlength", String.valueOf(data.length));
              Mat matHSV = new Mat(0,0,CvType.CV_64FC3);
  </code></pre>
  
  <p>Also by adding the following three lines of code, i'll receive an error saying bitmap == null, so im not really sure if the pixel reading worked or not.</p>
  
  <pre><code>matHSV.put(0,0,data);
  Utils.matToBitmap(matHSV, bb);
  imgDisplay.setImageBitmap(bb);
  </code></pre>
  
  <p><strong>EDIT2:</strong></p>
  
  <p>I'm getting an error when trying to specify the roi using <code>Rect</code>:</p>
  
  <blockquote>
    <p>Caused by: CvException [org.opencv.core.CvException: cv::Exception: /build/master_pack-android/opencv/modules/core/src/matrix.cpp:483: error: (-215) 0 &lt;= _rowRange.start &amp;&amp; _rowRange.start &lt;= _rowRange.end &amp;&amp; _rowRange.end &lt;= m.rows in function cv::Mat::Mat(const cv::Mat&amp;, const cv::Range&amp;, const cv::Range&amp;)</p>
  </blockquote>
  
  <pre><code>bitmap = globals.getBmp();
          Mat srcMat = new Mat();
          Utils.bitmapToMat(bitmap, srcMat);
  
          Mat hsvMat = new Mat();
          Imgproc.cvtColor(srcMat,hsvMat,Imgproc.COLOR_BGR2HSV);
  
      Mat roiMat;
              Rect rectangle = new Rect(177,1571,822,1680);// 177,1571(top right corner),   820,1680 (btm right) 820, 1565(topright)
              roiMat = new Mat(hsvMat,rectangle);
              Utils.matToBitmap(roiMat, temp);
  
              ImageView imageView = (ImageView) findViewById(R.id.imageView);
              imageView.setImageBitmap(temp);
  </code></pre>
  
  <p>I've also tried using <code>Range</code>:</p>
  
  <pre><code> Range rowRange = new Range(177, 822);
          Range colRange = new Range(1571, 1680);
          roiMat = new Mat(hsvMat, rowRange, colRange); // public Mat(Mat m, Range rowRange, Range colRange)
  </code></pre>
  
  <p><strong>EDIT2.5:</strong></p>
  
  <p>changing:</p>
  
  <pre><code>roiMat = new Mat(hsvMat, rowRange, colRange);
  </code></pre>
  
  <p>to:</p>
  
  <pre><code>roiMat = new Mat(hsvMat, colRange, rowRange); 
  </code></pre>
  
  <p>seemed to have fixed the issue, but now it's saying my bmp </p>
  
  <blockquote>
    <p>java.lang.IllegalArgumentException: bmp == null</p>
  </blockquote>
  
  <p><strong>EDIT 3:</strong>
  Finally managed to convert the python code answered by Alexander Reynolds,
  But i cant seem to view the result as I'm getting an error:</p>
  
  <blockquote>
    <p>java.lang.IllegalArgumentException: bmp == null</p>
  </blockquote>
  
  <p>at</p>
  
  <p><code>Utils.matToBitmap(idk,temp);</code></p>
  
  <pre><code>bitmap = cn.getBmp();
      Mat srcMat = new Mat();
      Utils.bitmapToMat(bitmap, srcMat);
  
      Mat hsvMat = new Mat();
      Imgproc.cvtColor(srcMat,hsvMat,Imgproc.COLOR_BGR2HSV);
  
      Mat roiMat;
      Rect rectangle = new Rect(177,1571,822,1680);// 177,1571(top right corner),   820,1680 (btm right) 820, 1565(topright)
      Range rowRange = new Range(177, 822);
      Range colRange = new Range(1571, 1680);
      roiMat = new Mat(hsvMat, colRange, rowRange); // public Mat(Mat m, Range rowRange, Range colRange)
  
      MatOfDouble mu = new MatOfDouble();
      MatOfDouble sig = new MatOfDouble();
  
      Core.meanStdDev(roiMat,mu,sig);
  
  
      double m = mu.get(0,0)[0];
      double d = sig.get(0,0)[0];
      int a = 9;
      Log.e("m , d", "m "+String.valueOf(m)+" d"+String.valueOf(d));
      Mat blue_mask = new Mat();
      Core.inRange(hsvMat, new Scalar(m-a*d), new Scalar(m+a*d), blue_mask); // javadoc: inRange(src, lowerb, upperb, dst)
      Mat idk = new Mat();
      Core.bitwise_and(hsvMat,hsvMat,idk,blue_mask);
      Utils.matToBitmap(idk,temp);
      Bitmap mutableBitmap = temp.copy(Bitmap.Config.ARGB_8888, true);
  </code></pre>