I have started working on OpenCv4Android recently.I was able to successfully run Image Manipulations Sample given.I wanted to covert RGB image to HSV as a test exercise.I have done OpenCv on C++(WINDOWS) and know basic functions too.
So the cvtcolor fucntions take the following arguments:
cvtcolor(mat src,mat dst,Imgproc.COLOR_TRANSFORMATION_TYPE,Number of Channels);
I tried different methods to check the output but I get only the cameraPreview that is the LIVE CAMERA view.Note:Other Functions like Canny Still work(shows OUTPUT).
Also I have doubt that is it neccessary to use JNI i.e NDK for this purpose or can most of the applications using OPENCV Library can me done(written) in main_activity.java and compiled??
I am starter to OpenCv4Android.Sorry If I have been over-descriptive and all suggestions are welcome. Thank You.
//METHOD 1
case ImageManipulationsActivity.VIEW_MODE_HSV:
rgba=inputFrame.rgba();
rgbaInnerWindow = rgba.submat(top, top + height, left, left + width);
Imgproc.cvtColor(rgba, mIntermediateMat, Imgproc.COLOR_RGB2HSV_FULL);
Imgproc.cvtColor(mIntermediateMat, rgbaInnerWindow, Imgproc.COLOR_HSV2RGB_FULL);
rgbaInnerWindow.release();
break;
//METHOD 2
case ImageManipulationsActivity.VIEW_MODE_HSV:
Mat hsv= null;
// rgba=inputFrame.rgba();
// rgbaInnerWindow = rgba.submat(top, top + height, left, left + width);
Imgproc.cvtColor(rgbaInnerWindow, mIntermediateMat, Imgproc.COLOR_RGBA2RGB);
Imgproc.cvtColor(mIntermediateMat, hsv, Imgproc.COLOR_RGB2HSV_FULL);
Imgproc.cvtColor(hsv, rgbaInnerWindow, Imgproc.COLOR_HSV2RGB_FULL);
rgbaInnerWindow.release();
break;
//METHOD 3
case ImageManipulationsActivity.VIEW_MODE_HSV:
rgbaInnerWindow = rgba.submat(top, top + height, left, left + width);
Imgproc.cvtColor(rgbaInnerWindow, rgbaInnerWindow, Imgproc.COLOR_HSV2RGB_FULL);
rgbaInnerWindow.release();
break;
If you want to display HSV format image, try this code (I havn't tested it, but it should work.)
Mat mRgba = inputFrame.rgba();
// mBgr is Mat in BGR Format
Imgproc.cvtColor(rgba, mBgr, Imgproc.COLOR_RGBA2BGR, 3);
// mHsv is Mat in Hsv Format
Imgproc.cvtColor(mBgr, mHsv, Imgproc.COLOR_BGR2HSV, 3);
// To display the image, we assume that mHsv is in BGR
Imgproc.cvtColor(mHsv, mRgb, Imgproc.COLOR_BGR2RGBA, 4);
// Display the image
Also I have doubt that is it neccessary to use JNI i.e NDK for this
purpose or can most of the applications using OPENCV Library can me
done(written) in main_activity.java and compiled??
No, you do not need to write native code for this, for most applications OpenCV Java bindings are sufficient. Even if you need to do it's pretty easy to do.
Related
Not sure if this is the right way to ask, but please help. I have an image of a dented car. I have to process it and highlight the dents and return the number of dents. I was able to do it reasonably well with the following result:
The matlab code is:
img2=rgb2gray(i1);
imshow(img2);
img3=imtophat(img2,strel('disk',15));
img4=imadjust(img3);
layer=img4(:,:,1);
img5=layer>100 & layer<250;
img6=imfill(img5,'holes');
img7=bwareaopen(img6,5);
[L,ans]=bwlabeln(img7);
imshow(img7);
I=imread(i1);
Ians=CarDentIdentification(I);
However, when I try to do this using opencv, I get this:
With the following code:
Imgproc.cvtColor(source, middle, Imgproc.COLOR_RGB2GRAY);
Imgproc.equalizeHist(middle, middle);
Imgproc.threshold(middle, middle, 150, 255, Imgproc.THRESH_OTSU);
Please tell me how can I obtain better results in opencv, and also how to count the dents? I tried findcontour() but it gives a very large number. I tried on other images as well, but I'm not getting proper results.
Please help.
So you basically from the MATLAB site, imtophat does - Top-hat filtering computes the morphological opening of the image (using imopen) and then subtracts the result from the original image.
You could do this in OpenCV with the following steps:
Step 1: Get the disk structuring element
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15))
Step 2: Compute opening of the image and then subtract the result from the original image
tophat = cv2.morphologyEx(v, cv2.MORPH_TOPHAT, kernel)
This gives following result -
Step 3 - Now you could just manually threshold it or use Otsu -
ret, thresh = cv2.threshold(tophat, 17, 255, 0)
which gives you the following image -
Since the OP wants the code in Java, here is the probable code in Java:
private Mat topHat(Mat image)
{
Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(15, 15), new Point (0, 0));
Mat dst = new Mat;
Imgproc.morphologyEx(image, dst, Imgproc.MORPH_TOPHAT, element, new Point(0, 0));
return dst;
}
Make sure you do this on a gray scale image (CvType.8UC1) and then you can threshold suitably.
i'm currently developing an android application to recognize digital numbers of an electricity meter. i've done most of the work but i still not getting a good result. 80% of the time i get a false one.
This is an example (i'm testing with a kitchen scale which is very similar to the meter) :
Original photo :
image after cropping and processing with OpenCV :
image after OCR (expected result that was obtained after several shots) :
image after OCR (unexpected result which is obtained often) :
Method used to process the image with OpenCV :
public Bitmap Bildverarbeitung (Bitmap image){
Mat tmp = new Mat (image.getWidth(), image.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(image, tmp);
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_RGB2GRAY);
Imgproc.GaussianBlur(tmp, tmp, new Size(3, 3), 0);
Imgproc.threshold(tmp, tmp, 0, 255, Imgproc.THRESH_OTSU);
Utils.matToBitmap(tmp, image);
return image;
}
I used two trained data but only one works better :
traineddata that works good
traineddata that doesn't work
can anyone help me get better results.. Is there any changes that i can do? or other methods that i can apply ? thanks in advance
I am new to OpenCv4Android. I am trying to auto detect document using OpenCv4Android sdk. Initially i have gone through issue of landscape opencv camera . Somehow i managed to change the orientation of opencv JavaCameraview to portrait. I made following changes in default classes of opencv sdk to orient opencv camera in portrait :
1) In CameraBridgeViewBase class
Matrix matrix = new Matrix();
matrix.setRotate(90f);
Bitmap bitmap = Bitmap.createBitmap(mCacheBitmap, 0, 0, mCacheBitmap.getWidth(), mCacheBitmap.getHeight(), matrix, true);
2) now in drawbitmap method replace above bitmap with mCacheBitmap
3) now , In JavaCameraView class
if ((getLayoutParams().width == ActionBar.LayoutParams.MATCH_PARENT) && (getLayoutParams().height == ActionBar.LayoutParams.MATCH_PARENT))
mScale = Math.min(((float)height)/mFrameWidth, ((float)width)/mFrameHeight);
else
mScale = 0;
After above changes , i am able to orient camera in portrait mode . But , having strange issue in detecting document . See below images
As you can see in first image , before customization i can detect paper in full green color . And in 2nd image you can see the bug of drawing line (drawContours) around paper
what i follow to detect paper is : GaussianBlur -> Canny edge detection -> findContours -> drawContour
In OnCameraFrame method :
mRgba = inputFrame.rgba();
Mat mGray = new Mat();
Mat edged = new Mat();
Imgproc.cvtColor(mRgba,mGray,Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(mRgba,mGray,new Size(5,5),0);
-> and then finding contours
Imgproc.findContours(edged, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
-> Then i found the largest contour and finally the drawContours on that
Imgproc.drawContours(mRgba, contours, maxI, new Scalar(0, 255, 0), 5);
I don't know where i m wrong..! Please help me to solve this strange issue.
#Rick M. following is the original image :
#ilke444 , following is the image after edge detection which is perfectly what i want :
I posted a little part of my code, cause i keep getting a strange error that I can't seem to get rid of. The problem can be found on this line: Imgproc.GaussianBlur(mGray, mGray, new Size (5,5), 2.2, 2);
public Mat onCameraFrame(Mat inputFrame) {
mGray = new Mat();
Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_RGBA2GRAY);
// doing a gaussian blur prevents getting a lot of false hits
Imgproc.GaussianBlur(mGray, mGray, new Size (5,5), 2.2, 2);
// Values 3 and 4are the LowerThreshold and UpperThreshold.
Imgproc.Canny(inputFrame, mIntermediateMat, 80, 100);
Imgproc.cvtColor(mIntermediateMat,mRgba, Imgproc.COLOR_GRAY2BGRA, 4);
return mIntermediateMat;
}
The error i get from Eclipse is:
The method GaussianBlur(Mat,Mat,Size,double,double) in
the type imgproc is not applicable for the arguments (Mat,Mat,CameraSize,int,int)
I am using an edited version of tutorial3 Camera-control (OpenCV for Android version 2.4.4) where the output is shown as Canny's edge detection. I need the GaussianBlur to get rid of some of the smaller details. Does anyone know what exactly is wrong in this line of the code?
This code works fine. Just reorder the parameters as you need.
Imgproc.GaussianBlur(mGray, mGray, new Size(15,15),50);
Size means that you will use it as kernel size. Also kernel size must be odd! 50 shows the kernel standard deviation in the X direction.
Formula : sigma = 0.3 * ((kSize-1)*0.5 - 1) + 0.8
Here sigma is passed 50 so sigmaX = sigmaY = 50
I got this solution from Alexander Smorkalov, and it worked. Just change the Imgproc.GaussianBlur(mGray, mGray, new Size (5,5), 2.2, 2); to Imgproc.GaussianBlur(mGray, mGray, new org.opencv.core.Size (5,5), 2.2, 2);
I am using OpenCV 2.3.1 in Android. I need to crop the image into half.
What I am doing is:
Mat mIntermediateMat2 = new Mat(frame_height,frame_width,rgba.type);
mIntermediateMat2 = rgba.clone();
mIntermediateMat2 = mIntermediateMat2.rowRange(0,frame_height/2);
Will the third step do the job or I have to add something more?
I saw Mat::operator() in opencv 2.3 documentation but unfortunately not able to find in the opencv Android package.
There are a few constructors for the Mat class, one of which takes a Mat and an ROI (region of interest).
Here's how to do it in Android/Java:
Mat uncropped = getUncroppedImage();
Rect roi = new Rect(x, y, width, height);
Mat cropped = new Mat(uncropped, roi);
I have always done cropping this way:
Mat image = ...; // fill it however you want to
Mat crop(image, Rect(0, 0, image.cols, image.rows / 2)); // NOTE: this will only give you a reference to the ROI of the original data
// if you want a copy of the crop do this:
Mat output = crop.clone();
Hope that helps!
Seems cv::getRectSubPix does what you want. Plus you don't have to allocate more space than you need. Also it does necessary interpolations if the cropped area is not aligned over an exact pixel.
This should do what you want. Input type will be the output type.
Mat dst;
getRectSubPix(src, Size(src.rows()/2,src.cols()), Point2f(src.rows()/4, src.cols()/2), dst);