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);
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 have recently started with JavaCv using Android for camera preview image processing.
Basically, I take the camera preview, do some processing, convert it to HSV to modify some colors, and then I want to convert it to RGBA to fill a bitmap.
Everything works normally, but quite slow. In order to find the slowest part I made some measurements, and to my surprise found this line:
cvCvtColor( hsvimage, imageBitmap, CV_HSV2RGB); //<-- 50msecs
where hsvimage is a 3-channel IplImage, and imageBitmap is 4 channel.image. (The conversion is good and leaves the alpha channel to 255, giving an opaque bitmap as expected)
Just for comparison, the following two lines only take 3msec
cvCvtColor(yuvimage, bgrimage, CV_YUV2BGR_NV21);
cvCvtColor(bgrimage, hsvimage, CV_BGR2HSV);
(yuvimage is 1 channel IplImage, bgrimage and hsvimage are 3 channel IplImages)
It seems as if the first conversion (HSV2RGB) isn't so much optimized as others. Also tested it with a 3-channel destination image, just in case, but with the same results.
I would like to find a way to make it as fast as BGR2HSV. Possible ways:
Find if there is another "equivalent" constant to CV_HSV2RGB which is
faster
Get direct access to the H-S-V byte arrays and make my own "fast" conversion
in C.
Any idea to solve this issue will be welcome
--EDIT--
All this is happening with a small 320*240 image and running on a Xiaomi Redmi Note 4. Most of the operations such as converting color from RGB to HSV take less than 1 msec. Canny takes 5msec, Floodfill takes about 5 or 6 msec. It is only this conversion HSV2RGB which gives such strange results.
Will try to use OpenCV directly (not JavaCV) to see if this behaviour disappears.
I was using an old JavaCV version (0.11) Now I have updated to 1.3 and results are nearly the same
...
long startTime=System.currentTimeMillis();
cvCvtColor(hsvimage, imageBitmap, CV_HSV2RGB);
Log.w(LOG_TAG, "Time:" + String.valueOf(System.currentTimeMillis() - startTime)); //<-- From 45 to 50msec
Log.w(LOG_TAG,"Channels:"+imageBitmap.nChannels()); // <-- returns 4
I can fill a 32bit/pixel android bitmap with the result
Mat mim4C= new Mat(imageBitmap);
Mat mhsvimage = new Mat(hsvimage);
long startTime**strong text**=System.currentTimeMillis();
CvtColor(mhsvimage, mim4C, CV_HSV2RGB);
Log.w(LOG_TAG, "Time:" + String.valueOf(System.currentTimeMillis() - startTime)); //<-- From 45 to 50mse
IplImage iim4C=new IplImage(mim4C);
Log.w(LOG_TAG,"Channels:"+iim4C.nChannels()); // <-- returns 3!!!
In this second case, if I try to fill a 32bits/pixel android bitmap (after converting back mim4C to IplImage), it crashes since it has 3 channels
I have read at several places (source, source) that OpenCV uses BGR color format by default.
But I am writing a class to detect a blob of a certain color (red) in an image (following the Color Blob Detection sample). So in the onCameraFrame(CvCameraViewFrame inputFrame) function, we return the value inputFrame.rgba(). According to the documentation,
rgba() This method returns RGBA Mat with frame
So I assumed that my rgbaFrame, which is the variable storing the value of inputFrame.rgba() in my program, contains the Mat in RGBA format.
But when I run the app, the red color in the original image appeared to be bluish in the rgbaFrame Mat I wrote to the external SD card. So apparently, the Mat is in BGR format, because red is appearing to be blue. (This is discussed in the comments of this question.)
So I changed my cvtColorfunction from
Imgproc.cvtColor(rgbaFrame, hsvImage, Imgproc.COLOR_RGB2HSV_FULL);
to
Imgproc.cvtColor(rgbaFrame, hsvImage, Imgproc.COLOR_BGR2HSV_FULL);
But nothing changed when I run the program. Red in original image still appears blue in the captured frame.
So now I am looking for a way to convert RGB to BGR format, to try and see if that helps solve my problem. But have failed to find one.
How do I convert BGR to RGB? Please share if you have any other suggestions for me.
original screenshot from which camera frame is captured:
rgbaFrame.jpg (because I did Highgui.imwrite("/mnt/sdcard/DCIM/rgbaFrame.jpg", rgbaFrame);//check)
OpenCV uses BGR by default, however, Android frame.rgba() implementation returns RGB (possibly for compliance with imageview and other Android components). However, the OpenCV function imwrite still requires BGR, therefore if you save the image without first converting it to BGR then the blue and red channels are saved incorrectly (swapped), because the Mat file of the frame has red channel in index 0 (RGB) whereas imwrite writes index 0 as blue (BGR). Similarly the frame has blue channel in index 2 whereas imwrite writes index 2 as red. You can call cvtcolor with COLOR_RGB2BGR before saving to a file.
/**
* Callback method that is called on every frame of the CameraBridgeViewBase class of OpenCV
*/
override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame?): Mat {
inputFrame?.let { currentFrame ->
val currentFrameMat = currentFrame.rgba()
// save the RGB2BGR converted version
val convertedMat = Mat()
Imgproc.cvtColor(currentFrameMat, convertedMat, Imgproc.COLOR_RGB2BGR)
Imgcodecs.imwrite(imageFilePath, convertedMat)
return currentFrameMat
}
return Mat()
}
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);