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);
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 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.
I have an image converted to CIELAB here. It works fine. However, when I conduct Thresholding using the Otsu method.
//convert to Greyscale
Imgproc.cvtColor(ImageMat, ImageMat, Imgproc.COLOR_RGB2Lab);
//threshold
Imgproc.threshold(ImageMat,ImageMat, 1, 128,Imgproc.THRESH_OTSU);
Wanted to achieve something like this: http://www.leptonica.com/binarization.html
While searching for solutions, most of the answers were general instructions such as advise to look at adaptive filter, gaussian blur, dilation and erosion but none of them provide any sample code to start with (so can play around with the values)..
I know different image require different methods and values to achieve optimum clarity, but I just need some general filter so that the image at least slightly sharper and less noisy compare to the original, before doing any OCR on it.
this is what I've tried so far..
Mat imageMat = new Mat();
Utils.bitmapToMat(photo, imageMat);
Imgproc.cvtColor(imageMat, imageMat, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(imageMat, imageMat, new Size(3, 3), 0);
Imgproc.adaptiveThreshold(imageMat, imageMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 5, 4);
but being an image processing newb, obviously I don't know what I'm doing XD
original image:
after applying the above:
How to do it correctly?
UPDATE: got it much closer thanks to metsburg, berak and Aurelius
Using the medianBlur method since cvSmooth with CV_MEDIAN is deprecated and replaced with medianBlur:
Imgproc.medianBlur(imageMat, imageMat, 3);
Imgproc.threshold(imageMat, imageMat, 0, 255, Imgproc.THRESH_OTSU);
Result:
Using back the GaussianBlur method, the result actually is slightly better:
Imgproc.GaussianBlur(imageMat, imageMat, new Size(3, 3), 0);
Imgproc.threshold(imageMat, imageMat, 0, 255, Imgproc.THRESH_OTSU);
Result:
For this image the difference is not noticable, so I tried another image which is a photo taken off the computer screen. Computer screen gives a lot of noises (wavy lines) so it is very hard to remove the noise.
Example original image:
Directly applying otsu:
using medianBlur before otsu:
using GaussianBlur before otsu:
Seems like gaussian blur is slightly better, however I'm still playing with the settings..
If anyone can advise on how to improve the computer screen photo further, please, let us know :)
One more thing.. using this method on the image inside the top link yields horrible results :( see it here: http://imgur.com/vOZAaE0
Well, you're almost there. Just try these modifications:
Instead of
Imgproc.GaussianBlur(imageMat, imageMat, new Size(3, 3), 0);
try:
cvSmooth(imageMat, imageMat, CV_MEDIAN, new Size(3, 3), 0);
check the syntax, may not exactly match
The link you posted uses thresholding of Otsu, so try this:
Imgproc.threshold(imageMat, imageMat, 0, 255, Imgproc.THRESH_OTSU);
for thresholding.
Try tweaking the parameters here and there, you should get something pretty close to your desired outcome.
Instead of using Imgproc.THRESH_BINARY_INV use Imgproc.THRESH_BINARY only as _INV is inverting your image after binarisations and resulted is the said output shown above in your example.
correct code:
Imgproc.adaptiveThreshold(imageMat, imageMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 5, 4);
I stumbled upon a weird problem with OpenCV drawContours on android.
Sometimes, (without apparent pattern) function drawContours produces this:
drawContours http://img17.imageshack.us/img17/9031/screenshotgps.png
while it should obviously produce just the white part.
To put it in context:
I detect edges using canny algorithm and then I find contours with
Imgproc.findContours(dil, contours, dummy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
Then i select several contours that fit some requirements and I add them to a list:
List<MatOfPoint> goodContours = new ArrayList<MatOfPoint>();
After that I randomly select one contour and I draw it (filled with white) on mat and convert it to android Bitmap:
Mat oneContour = new Mat(orig.rows(), orig.cols(), CvType.CV_8UC1);
int index = (int) (Math.random() * goodContours.size());
Imgproc.drawContours(oneContour, goodContours, index, new Scalar(255, 255, 255), -1);
Bitmap oneContourBitmap = Bitmap.createBitmap(oneContour.cols(), oneContour.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(oneContour, oneContourBitmap);
Most of the times I get what I expect: white patch on a pure black background, but sometimes I get the above. I'm totally at a loss here. I suspect there could be some memory leakage but I try hard to release all Mat's immediately after they are of no use anymore (I also tried to release them at the end of a function where it all happens but without effect) but I'm unable to pinpoint the source of the problem.
Has anyone had similar issues?
I first discovered this on OpenCV 2.4.0 but it stays the same on 2.4.3.
Any suggestion is appreciated.