Change hue of image - android

i have started working on opencv on android platform. I wanted to change the hue of image, not the whole just the sub part of it.
So how we do that
Change full image to hsv
then select that specific part (Matrix)
and change it's hue
then convert the image back to rgba (i am working on android so it
should b 4 channel. am i right??)
Or
Select that sub part (Matrix)
Change that sub part to hsv
Change it's hue
Convet back that specific part back to rgba
I have also try some code using second method i am not succeed yet. So i want some good examples or some guidance how to acheive that.

You can use OpenCV camera preview example from sample folder
Try below code
//Global variable
private Mat src;
Mat hsv = null;
private CameraBridgeViewBase mOpenCvCameraView;
List<Mat> hsv_channel= new ArrayList<Mat>();
---------------------------------------
----------------------------------------
// Initialize Mat here
public void onCameraViewStarted(int width, int height) {
src = new Mat(height, width, CvType.CV_8UC4);
hsv = new Mat(height, width, CvType.CV_8UC4);
}
-----------------------------------------
---------------------------------------
//Process Mat here
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
src = inputFrame.rgba();
Imgproc.cvtColor(src, hsv,Imgproc.COLOR_BGR2HSV );
Core.split(hsv, hsv_channel);
Imgproc.equalizeHist(hsv_channel.get(0), hsv_channel.get(0)); //Get hue channel and perform hsitogram equlization
Core.merge(hsv_channel, hsv);
Imgproc.cvtColor(hsv, src,Imgproc.COLOR_HSV2BGR );
return src;
}

Related

OpenCV - Apply method in BackgroundSubtractorMOG2 crashes Android Application after 5-10 seconds

I am developing one Android application using OpenCV where I have to implement Background Subtraction. I am able to see some frames in grayscale and background removed, it only lasts for a while though, and then the application crashes.
Technique used: BackgroundSubtractorMOG2
This is my snippet of OnCameraFrame
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
Mat frame = inputFrame.rgba();
Mat mRgb = new Mat();
Mat mFGMask = new Mat();
BackgroundSubtractorMOG2 mog2 = Video.createBackgroundSubtractorMOG2();
Imgproc.cvtColor(frame, mRgb, Imgproc.COLOR_RGBA2RGB);
mog2.apply(mRgb, mFGMask);
Imgproc.cvtColor(mFGMask, frame, Imgproc.COLOR_GRAY2RGBA);
return frame;
}
Thanks in advance.
I was able to solve my issue.
new Mat() which is used was causing an issue of memory management. It has to be initialized just once in onCameraViewStarted and the returning Mat has to be released in onCameraViewStopped. After modifying the code as per suggestions through the OpenCV community, I was able to execute my application properly.
1. Declare at the first
private Mat mRgb;
private Mat mFGMask;
private Mat frame;
private BackgroundSubtractorMOG2 mog2;
Initialize in onCameraViewStarted
public void onCameraViewStarted(int width, int height) {
mRgb = new Mat();
mFGMask = new Mat();
mog2 = Video.createBackgroundSubtractorMOG2();
}
Release the returning frame in onCameraViewStopped
public void onCameraViewStopped() {
frame.release();
}
For full code: https://github.com/rishirajrsawant/OpenCV-Background-Subtraction

Android OpenCV copy ROI to part of bigger image

I get a mat (320x480) from the camera of the phone. Then I need to process a part of that frame. I use ROI for that:
mat2 = new Mat(width, 175, CvType.CV_8SC3);
Rect roi = new Rect(75, 0, 175, 320);
mat2 = new Mat(mat1, roi);
Now I want to create a new mat with dimensions 320x480 with a black background. How do I do that?
Then I want to copy the processed ROI to the new mat at the same place it was on the first mat. How do I do that?
I am using OpenCV 3.4.6 and android studio.
Thank you in advance
You just need to submat() an ROI from the original Mat (your camera frame), and then process the submat as a normal Mat, but be careful to do not clone the sumbmat if you want the original get the effect.
Update according to the comment:
Mat originalMat = someMat;
Mat blackMat = Mat.zeros(size, CvType.CV_8UC1); // it is your black mat
// create a submat from the original mat, and clone it
Mat roiMat = originalMat.submat(rect).clone();
..... // do what you want with roiMat
// now copy the result to the original mat
Mat dst = originalMat.submat(rect); // do not clone this submat
roiMat.copyTo(dst);
// done!

Size of MAT in OpenCV android remain 1920*2560*CV_8UC4

I am new to android development to OpenCV. I have an image and I am doing some manipulation on image.I first converted my image into bitmap and then convert that bitmap into MAT like below.
Mat src = new Mat (400, 800, CvType.CV_8UC1, new Scalar(4));
Bitmap myBitmap32 = BitmapFactory.decodeFile(bitmap_file);
Utils.bitmapToMat(myBitmap32, src);
But when I run this, I am getting my mat to be
Mat [ 1920*2560*CV_8UC4, isCont=true, isSubmat=false, nativeObj=0x527a5950, dataAddr=0x54262010 ]
So,I am getting image size 1920x2560.
I want this size to be my original 400x800 .
From OpenCV Java docs:
The output Mat is always created of the same size as the input Bitmap and of the 'CV_8UC4' type, it keeps the image in RGBA format.
So, for resizing an image, you should first read the image to a Mat and then use resize() (from Imgproc):
public static void resize(Mat src, Mat dst, Size dsize)
public static void resize(Mat src, Mat dst, Size dsize, double fx, double fy, int interpolation)
As you want to shrink an image, it's recommended to use CV_INTER_AREA interpolation.

Set hue of image store in matrix

I am trying to change the hue of image store in matrix. I got a hue channel using split() function but i am not able to change its hue. I am using the function set(Scalar scalar) to change its hue, but i don't see any change in image.
Mat eyeball_HSV = new Mat();
Mat dest = new Mat();
Mat eye = new Mat();
eye = mRgba.submat(eye_template);
List<Mat> hsv_channel = new ArrayList<Mat>();
Imgproc.cvtColor(eye, eyeball_HSV, Imgproc.COLOR_RGB2HSV, 0);
// get HSV channel
//hsv_channel[0] is hue
//hsv_channel[1] is saturation
//hsv_channel[2] is visibility
Core.split(eyeball_HSV, hsv_channel);
try
{
hsv_channel.get(0).setTo(new Scalar(145,25,45));
Log.v(TAG, "Got the Channel!");
}
catch(Exception ex)
{
ex.printStackTrace();
Log.v(TAG, "Didn't get any channel");
}
Imgproc.cvtColor(eyeball_HSV, dest, Imgproc.COLOR_HSV2RGB);
Imgproc.cvtColor(dest, eye, Imgproc.COLOR_RGB2RGBA);
Just change the code
hsv_channel.get(0).setTo(new Scalar(145,25,45));
to
hsv_channel.get(0).setTo(new Scalar(145)); // whatever your value
hsv_channel.get(0) is single channel Mat so your Scalar value should be with single.
Edit:-
Yo can see the OpenCV camera preview example here
On Tutorial1Activity.java you can see a method
public Mat onCameraFrame(CvCameraViewFrame inputFrame)
Add these lines on this method
src = inputFrame.rgba();
Imgproc.cvtColor(src, hsv,Imgproc.COLOR_RGB2HSV );
Core.split(hsv, hsv_channel);
// Imgproc.equalizeHist(hsv_channel.get(0), hsv_channel.get(0));
hsv_channel.get(0).setTo(new Scalar(64));
Core.merge(hsv_channel, hsv);
Imgproc.cvtColor(hsv, src,Imgproc.COLOR_HSV2RGB );
//return hsv_channel.get(0);
return src;

How to convert floating point image to 32bit single channel in OpenCv?

I'm doing a watershed segmentation and the marker image is derived from the source image put through a distance transform. The distance transform returns a floating point image (I have no idea about the bit-depth) and I have trouble putting it through the watershed method since it requires a 32 bit single channel image.
Can I use the mat's convertTo method to set the bit depth to 32?
I also have trouble trying to display the floating point image since the matToBitmap() method doesn't seem to accept them. (in Android)
Mat mImg = new Mat();
Mat mThresh = new Mat();
Mat mDist = new Mat();
ImageView imgView = (ImageView) findViewById(R.id.imageView);
Bitmap bmpIn = BitmapFactory.decodeResource(getResources(),
R.drawable.w1);
Utils.bitmapToMat(bmpIn, mImg);
Imgproc.cvtColor(mImg, mImg, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(mImg, mThresh, 0, 255, Imgproc.THRESH_BINARY
| Imgproc.THRESH_OTSU);
//Marker image for watershed
Imgproc.distanceTransform(mThresh, mDist, Imgproc.CV_DIST_L2, Imgproc.CV_DIST_MASK_PRECISE);
//Conversions for watershed
Imgproc.cvtColor(mThresh, mThresh, Imgproc.COLOR_GRAY2BGR, 3);
//Floating-point image -> 32-bit single-channel
mDist.convertTo(...);
Imgproc.watershed(mThresh, mDist); //
Bitmap bmpOut = Bitmap.createBitmap(mThresh.cols(), mThresh.rows(),
Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mThresh, bmpOut);
imgView.setImageBitmap(bmpOut);
Yes, you can use the convertTo function to convert any opencv matrix to another type. The type to convert to should be set in a destination matrix with the same size. convertTo has optional parameters scale and shift, so you can avoid clipping and quantization errors when converting to fixed point depths. So for your code:
Mat mDist32 = Mat(mDist.rows,mDist.cols,CV_32SC1); // 32 bit signed 1 channel, use CV_32UC1 for unsigned
mDist.convertTo(mDist32,CV_32SC1,1,0);
Imgproc.watershed(mThresh,mDist32);

Categories

Resources