Android Watershed OpenCV - java

My Question how to count Objects in image on Android Watershed OpenCv?

Since you didn't tell us which line causes those problem, but i strongly assume you misused erode() and dilate().
You should pass 3rd parameter of each function with valid non-zero Matrix.(e.g. Kernel)
erode & dilate example
// You can change the size of kennel
// if you want to change the range of erosion & dilation
Mat kelnel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2,2));
Mat fg = new Mat(img.size(),CvType.CV_8U);
Imgproc.erode(threeChannel, fg, kelnel);
Mat bg = new Mat(img.size(),CvType.CV_8U);
Imgproc.dilate(threeChannel, bg, kelnel);

Related

How to get connectedComponents with stats in android java using opencv and how to use these stats to get left point, right pint, centroid, area etc

Please clear I am new at android and java
I have used this code but don't know what is meaning of these four variables
Imgproc.connectedComponentsWithStats(binarized, labeled, rectComponents, centComponents);
Mat tmp = new Mat(bmp.getWidth(), bmp.getHeight(), CvType.CV_8U);
Utils.bitmapToMat(bmp, tmp);
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_RGB2GRAY);
Imgproc.threshold(tmp, tmp, 40, 255, Imgproc.THRESH_BINARY);
Imgproc.GaussianBlur(tmp, tmp, new org.opencv.core.Size(5, 5), 0 , 0);
Imgproc.threshold(tmp,tmp,130,255,Imgproc.THRESH_OTSU);
Utils.matToBitmap(tmp, bmp);
imageView.setImageBitmap(bmp);```
I want to get connected components with stats of tmp.
Thanks guys, I am answering my own question. I have found how to do it.
int a = Imgproc.connectedComponentsWithStats(image,labels,stats,centroid);
this function returns an integer which is the number of connected components in the image(Mat OpenCV) which is passing to the function (first argument).
labels is a Mat datatype array which is of the size of the input image with the value of each pixel is label of that pixel in the original image
centroid is centroid of each label(x,y).
stats tells us area of the label and position of the label(return leftmost pixel, topmost pixel,width,height)

OCR Preprocessing: Remove lines crossing characters

I'm currently trying to improve the recognition rate of GoogleCloud Vision, so I am building a preprocessing pipeline.
I currently can create a mask which overlays the characters in the image, but as you can see in the examples below, it also shows the lines. Now since those lines can cross through characters, I'd like to remove them from the mask without destroying the characters, if possible.
Current steps:
Line detection:
InputImage -> Grayscale -> Blackhat -> GaussianBlur -> Threshhold(OTSU) -> HoughLinesP
Mask generation: InputImage -> Grayscale -> Blackhat -> GaussianBlur -> Threshhold(OTSU)-> ConnectedComponents
ImageExamples:(Due to privacy protection, sharing a full Image is not possible)
The images show the original image, the mask and the lines recognized.
The following code is used to generate the mask and find the lines
Mat picture = Imgcodecs.imread(path);
Imgproc.cvtColor(picture, picture, Imgproc.COLOR_BGR2GRAY);
Imgcodecs.imwrite("/home/meik/Pictures/asdfGray.png", picture);
Mat blackhatElement = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(7, 7));
Imgproc.morphologyEx(picture, picture, Imgproc.MORPH_BLACKHAT, blackhatElement);
Imgproc.GaussianBlur(picture, picture, new Size(5, 3), 0);
Imgproc.threshold(picture, picture, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
/**
* Line Detection with Canny and HoughLines(P)
*/
Mat lines = new Mat();
Mat linesResult = Mat.zeros(picture.rows(),picture.cols(), CvType.CV_8UC1);
Imgproc.HoughLinesP(picture, lines,1, Math.PI/180,100, 20, 0);
System.out.println("lines rows:" + lines.rows());
for (int x = 0; x < lines.rows(); x++) {
double[] l = lines.get(x, 0);
Imgproc.line(linesResult, new Point(l[0], l[1]), new Point(l[2], l[3]), new Scalar(255, 255, 255), 1, Imgproc.LINE_8, 0);
}
/**End of line detection*/
Mat kernel = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_CROSS, new Size(3,3));
Imgproc.dilate(linesResult,linesResult,kernel);
Core.bitwise_not(linesResult,linesResult);
I've found this paper talking about the problem, but am struggling to understand their methodology.
How do I proceed from here on to remove lines without destroying the characters?
I dont really think you need to refer paper to do this.
Just use color info or hough line to find out a straightline which is really long
use that info to create a mask image.
Then use the opencv inpaint to remove it.
https://docs.opencv.org/2.4/modules/photo/doc/inpainting.html
e.g. what you want is similar to the bottom image. It ask to remove the traffic light poles. and you want the writing guideline to be removed. essentially, its the same thing
How about some simple image preprocessing?
For example using a threshold to only maintain a certain color range (instead of directly converting the image to grayscale).
Something like this is integrated in GIMP, see
https://docs.gimp.org/2.8/en/gimp-tool-threshold.html
You probably want to experiment with various thresholds.

Join different sized images with ROI

At the first contact with Java OpenCV (3.3.1, windows 8 x64) I'm trying to join two different size images with ROI dynamically. Here a bit of my code:
Mat _mat = Utils.imageFileToMat(new File("angelina_jolie.jpg")); //Angelina's face
Mat grayMat = new Mat();
Imgproc.cvtColor(_mat, grayMat, Imgproc.COLOR_BGR2GRAY);
Rect rect = new Rect(new Point(168, 104), new Point(254, 190)); //Angelina's eye ROI
Mat truncated = _mat.submat(rect); //Angelina's eye mat
Mat merge = _mat.clone();
truncated.copyTo(merge);
//show _mat
//show truncated
//show merge
What I want to see is Angelina Jolie with her eye on grayscale.
What I see is assertions or the truncated image only (just the eye).
I tried with copyTo(mat, mask), setOf, and a lot of things but always get a new assertion.
Should I change the size of truncated to the size of mat to match sizes? how can I do that programmatically?
Mat::copyTo documentation:
The method copies the matrix data to another matrix. Before copying
the data, the method invokes :
m.create(this->size(),this->type());
so that the destination matrix is reallocated
if needed. While m.copyTo(m); works flawlessly, the function does not
handle the case of a partial overlap between the source and the
destination matrices.
When the operation mask is specified, if the Mat::create call shown
above reallocates the matrix, the newly allocated matrix is
initialized with all zeros before copying the data.
#param m
Destination matrix. If it does not have a proper size or type before
the operation, it is reallocated.
Since you're your src and dst images don't have the same size and channels, the destination image is reallocated and initialized with zeros. To avoid that make sure both images have same dimensions and number of channels.
Imgproc.cvtColor(grayMat, grayMat, Imgproc.COLOR_GRAY2BGR);
Now create a mask:
Mat mask = new Mat(_mat.size(), CvType.CV_8UC1, new Scalar(0));
Imgproc.rectangle(mask, new Point(168, 104), new Point(254, 190),new Scalar(255));
// copy gray to _mat based on mask
Mat merge = _mat.clone();
grayMat.copyTo(merge,mask);

color detection using opencv

I am trying to extract the title bar from the image below using opencv.
I am using the following code -
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat original = Imgcodecs.imread("D:/test_bg_extract.png", Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
Mat hsvMat = new Mat();
Imgproc.cvtColor(original, hsvMat, Imgproc.COLOR_BGR2HSV);
Mat dst = new Mat();
Core.inRange(hsvMat, new Scalar(23,231,205), new Scalar(23,231,205), dst);
I used a color picker to determine the HSV value of the title bar (from the hsvMat converted to display image). When the run the code to display the output, I see a blank screen. I can't tell what I am doing wrong. Am I picking the wrong HSV color? If I know the exact RGB code then should I even be converting image to HSV? (this however seems to be the standard method from many code examples on the internet).
Ok, I solved it using RGB based color, switching to BGR while specifying the color that I need. So this worked -
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat original = Imgcodecs.imread("D:/test_bg_extract.png", Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
Mat dst = new Mat();
Core.inRange(original, new Scalar(132,178,205), new Scalar(132,178,205), dst);

How to scale a Mat in OpenCV

I'm frustrated trying to find a method that would allow me to scale a Mat object to a different size. Please, could anybody help me with this?
My project is using the Java wrapper, but I'll be happy if the answer provided is for the C++ native OpenCV library.
If by resizing you mean scaling an image use the resize() function as follows:
resize(src, dst, dst.size(), 0, 0, interpolation);
Otherwise if you just need to change the number of rows of your Mat use the Mat::reshape() function. Pay attention that the reshape return a new Mat header:
cv::Mat dst = src.reshape ( 0, newRowVal );
Finally if you want to arbitrarily reshape the Mat (changing rows and cols) you probably need to define a new Mat with the destination dimensions and copy the src Mat to it:
Mat dst(newRowVal, newColVal, src.type());
src.setTo(0);
src.copyTo(dst(Rect(Point(0, 0), src.size())));
You can use resize() function
Create a new Mat result of new dimensions
resize(input // input image
result // result image
result.size() // new dimensions
0,
0,
INTER_CUBIC // interpolation method
);
to know more interpolation methods, you can check this doc: geometric_transformations.html#resize

Categories