Я новичок в OpenCV4Android. Вот код, который я написал для обнаружения синего пятна на изображении. Среди следующих изображений изображение 1 было в моем ноутбуке. Я запускаю приложение, и кадр, захваченный камерой OpenCV, является изображением 2. Вы можете посмотреть код, чтобы увидеть, что представляют собой остальные изображения. (Как видно из кода, все изображения сохраняются на SD-карте.)
У меня есть следующие вопросы:.
Почему цвет светло-голубого пятна оказался светло-желтым в кадре rgba, снятом камерой (показано на изображении 2).
Я создал
boundingRect
вокруг самого большого синего пятна, а затемROI
, выполнивrgbaFrame.submat(detectedBlobRoi)
. Но вы можете видеть на последнем изображении, это выглядит как пара серых пикселей. Я ожидал, что синяя сфера будет отделена от остального изображения.
Что я упускаю или делаю неправильно?
КОД:
private void detectColoredBlob () {
Highgui.imwrite("/mnt/sdcard/DCIM/rgbaFrame.jpg", rgbaFrame);//check
Mat hsvImage = new Mat();
Imgproc.cvtColor(rgbaFrame, hsvImage, Imgproc.COLOR_RGB2HSV_FULL);
Highgui.imwrite("/mnt/sdcard/DCIM/hsvImage.jpg", hsvImage);//check
Mat maskedImage = new Mat();
Scalar lowerThreshold = new Scalar(170, 0, 0);
Scalar upperThreshold = new Scalar(270, 255, 255);
Core.inRange(hsvImage, lowerThreshold, upperThreshold, maskedImage);
Highgui.imwrite("/mnt/sdcard/DCIM/maskedImage.jpg", maskedImage);//check
Mat dilatedMat= new Mat();
Imgproc.dilate(maskedImage, dilatedMat, new Mat() );
Highgui.imwrite("/mnt/sdcard/DCIM/dilatedMat.jpg", dilatedMat);//check
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(dilatedMat, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
//Use only the largest contour. Other contours (any other possible blobs of this color range) will be ignored.
MatOfPoint largestContour = contours.get(0);
double largestContourArea = Imgproc.contourArea(largestContour);
for ( int i=1; i<contours.size(); ++i) {//NB Notice the prefix increment.
MatOfPoint currentContour = contours.get(0);
double currentContourArea = Imgproc.contourArea(currentContour);
if (currentContourArea > largestContourArea) {
largestContourArea = currentContourArea;
largestContour = currentContour;
}
}
Rect detectedBlobRoi = Imgproc.boundingRect(largestContour);
Mat detectedBlobRgba = rgbaFrame.submat(detectedBlobRoi);
Highgui.imwrite("/mnt/sdcard/DCIM/detectedBlobRgba.jpg", detectedBlobRgba);//check
}
- Исходное изображение на компьютере. Это было снято путем размещения камеры телефона перед экраном ноутбука.
- rgbaFrame.jpg
- hsvImage.jpg
- растянутое изображение.jpg
- Маскированный мат.jpg
- обнаруженBlobRgba.jpg
ИЗМЕНИТЬ:
Я только что использовал Core.inRange(hsvImage, new Scalar(0,50,40), new Scalar(10,255,255), maskedImage);//3, 217, 225 --- 6, 85.09, 88.24 ...... 3 219 255
и сделал скриншот веб-сайта colorizer.org, задав ему пользовательские значения HSV для красного цвета, то есть для красного цвета OpenCV Scalar(3, 217, 255)
(который попадает в диапазон, установленный в данной функции inRange
, я масштабировал канал значения по шкале colorizer.org, которая составляет H = 0–360, S = 0–100, V = 0–100, путем умножения значения H на 2 и деления значений S и V на 255 и умножения на 100. , Это дало мне 6, 85.09, 88.24
, который я установил на веб-сайте, и сделал скриншот (первый на следующих изображениях).
- Оригинальный скриншот, я заснял этот кадр.
- rgbaFrame.jpg
- hsvImage.jpg
- МаскированныйИзображение.jpg
- растянутый мат.jpg
- обнаруженBlobRgba.jpg
ВАЖНО:
Данный метод фактически вызывается в моем тестовом приложении, когда я касаюсь внутри rgbaFrame (т.е. он вызывается внутри метода onTouch
). Я также использую следующий код для печати в TextView
значений Hue
, Saturation
и Value
цветного пятна, к которому я прикоснулся. Запустив это приложение, я коснулся красной точки и получил следующие значения: Hue:3, Saturation:219, Value:255
.
public boolean onTouch(View v, MotionEvent motionEvent) {detectColoredBlob(); int cols = rgbaFrame.cols(); целые строки = rgbaFrame.rows();
int xOffset = (openCvCameraBridge.getWidth() - cols) / 2;
int yOffset = (openCvCameraBridge.getHeight() - rows) / 2;
int x = (int) motionEvent.getX() - xOffset;
int y = (int) motionEvent.getY() - yOffset;
Log.i(TAG, "Touch image coordinates: (" + x + ", " + y + ")");//check
if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) { return false; }
Rect touchedRect = new Rect();
touchedRect.x = (x > 4) ? x - 4 : 0;
touchedRect.y = (y > 4) ? y - 4 : 0;
touchedRect.width = (x + 4 < cols) ? x + 4 - touchedRect.x : cols - touchedRect.x;
touchedRect.height = (y + 4 < rows) ? y + 4 - touchedRect.y : rows - touchedRect.y;
Mat touchedRegionRgba = rgbaFrame.submat(touchedRect);
Mat touchedRegionHsv = new Mat();
Imgproc.cvtColor(touchedRegionRgba, touchedRegionHsv, Imgproc.COLOR_RGB2HSV_FULL);
double[] channelsDoubleArray = touchedRegionHsv.get(0, 0);//**********
float[] channelsFloatArrayScaled = new float[3];
for (int i = 0; i < channelsDoubleArray.length; i++) {
if (i == 0) {
channelsFloatArrayScaled[i] = ((float) channelsDoubleArray[i]) * 2;// TODO Wrap an ArrayIndexOutOfBoundsException wrapper
} else if (i == 1 || i == 2) {
channelsFloatArrayScaled[i] = ((float) channelsDoubleArray[i]) / 255;// TODO Wrap an ArrayIndexOutOfBoundsException wrapper
}
}
int androidColor = Color.HSVToColor(channelsFloatArrayScaled);
view.setBackgroundColor(androidColor);
textView.setText("Hue : " + channelsDoubleArray[0] + "\nSaturation : " + channelsDoubleArray[1] + "\nValue : "
+ channelsDoubleArray[2]);
touchedRegionHsv.release();
return false; // don't need subsequent touch events
}
Imgproc.COLOR_RGB2HSV_FULL
наImgproc.Imgproc.COLOR_BGR2HSV_FULL
, но это ничего не изменило (красный цвет на исходном изображении по-прежнему выглядит голубоватым в rgbaFrame). Затем я подумал, что, возможно, мне придется использоватьcvtColor
для преобразованияrgbaFrame
в формат BGR, когда он создается в функцииonCameraFrame
с помощьюrgbaFrame = inputFrame.rgba()
, но здесь в документации не упоминается преобразование из RGB в BGR. - person Solace   schedule 09.12.2015