Cropping image in Android using opencv - android

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);

Related

Blurring a Rect within a screenshot

I'm developing an Android app which uses a background Service to programmatically capture a screenshot of whatever is on the screen currently. I obtain the screenshot as a Bitmap.
Next, I successfully imported OpenCV into my Android project.
What I need to do now is blur a subset of this image, i.e. not the entire image itself, but a [rectangular] area or sub-region within the image. I have an array of Rect objects representing the rectangular regions that I need to blur within the screenshot.
I've been looking around for a tutorial on doing this with OpenCV in Java, and I haven't found a clear answer. The Mat and Imgproc classes are obviously the ones of interest, and there's the Mat.submat() method, but I've been unable to find a clear, straightforward tutorial on getting this done.
I've googled a lot, and none of the examples I've found are complete. I need to do this in Java, within the Android runtime.
What I need is: Bitmap >>> Mat >>> Imgproc>>> Rect >>> Bitmap with ROI
blurred.
Any experienced OpenCV devs out here, can you point me in the right direction? This is the only thing I'm stuck at.
Related:
Gaussian blurring with OpenCV: only blurring a subregion of an image?.
How to blur a rectagle with OpenCv.
How to blur some portion of Image in Android?.
The C++ code to achieve this task is shared below with comments and sample images:
// load an input image
Mat img = imread("C:\\elon_tusk.png");
img:
// extract subimage
Rect roi(113, 87, 100, 50);
Mat subimg = img(roi);
subimg:
// blur the subimage
Mat blurred_subimage;
GaussianBlur(subimg, blurred_subimage, Size(0, 0), 5, 5);
blurred_subimage:
// copy the blurred subimage back to the original image
blurred_subimage.copyTo(img(roi));
img:
Android equivalent:
Mat img = Imgcodecs.imread("elon_tusk.png");
Rect roi = new Rect(113, 87, 100, 50);
Mat subimage = img.submat(roi).clone();
Imgproc.GaussianBlur(subimg, subimg, new Size(0,0), 5, 5);
subimg.copyTo(img.submat(roi));
You could just implement your own helper function, let's call it roi (region of interest).
Since images in opencv are numpy ndarrays, you can do something like this:
def roi(image: np.ndarray, region: QRect) -> np.ndarray:
a1 = region.upperLeft().x()
b1 = region.bottomRight().y()
a2 = region.upperLeft().x()
b2 = region.bottomRight().y()
return image[a1:a2, b1:b2]
And just use this helper function to extract the subregions of the image that you are interested, blur them and put the result back on the original picture.

Thresholding in Android using opencv

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.

Using OpenCV4Android, how to create an ROI (Region-Of-Interest or a submat) from a contour?

Given an image Mat, and a contour (which is a MatOfPoint) in it, how can I create a ROI (Region Of Interest)/submat?
I can see three interesting methods on docs of Mat,
Mat submat(int rowStart, int rowEnd, int colStart, int colEnd)
Extracts a rectangular submatrix.
Mat submat(Range rowRange, Range colRange)
Extracts a rectangular submatrix.
Mat submat(Rect roi)
Extracts a rectangular submatrix.
Is there a way to find out rowStart, rowEnd, colStart and
colEnd from the contour?
or
Is there a way to get rowRange and colRange from the contour?
or
Can I make a Rect from the contour?
Use Imgproc.boundingRect(MatOfPoint contour) method. This way you can use the third of the submat() methods you have listed:
Rect roiRect = Imgproc.boundingRect(contour);
Mat roiSubmat = originalMat.submat(roiRect);
roiSubmat is your region of interest (stored in a Mat).

Converting RGB2HSV in OPENCV4Android

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.

digit detection from the image in android

I am searching for how to extract a digital number from the image in android. I have to take a picture then i need to get numbers from image. OpenCV is a option . can we convert opencv into android ? Kindly suggest me any proper way. I will be grateful to you.
There are many OCR for Android
check there links
https://github.com/rmtheis/android-ocr
https://github.com/GautamGupta/Simple-Android-OCR
http://www.abbyy.com/mobileocr/android/
best OCR (Optical character recognition) example in android
OpenCV supports Android platform. You have to set up OpenCV4Android, it's instructions step by step here.
http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/O4A_SDK.html
However OpenCV is not an option but only a step. Then you have to use a character recognition engine. Most popular one is Tesseract-ocr. But it is really not easy task.
Also, they often recognize all characters. If you could achieve it, extracting the digits will be the easiest part in Java.
this works for me you just need to specify the number size` ArrayList output=new ArrayList<>();
cvtColor(input,input,COLOR_BGRA2GRAY);
Mat img_threshold = new Mat();
threshold(input, img_threshold, 60, 255,THRESH_BINARY_INV);
Mat img_contours =copy(img_threshold);
//Find contours of possibles characters
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
findContours(img_contours, contours,new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE); // all pixels of each contours
contours=sort(contours);
// Draw blue contours on a white image
Mat result=copy(img_threshold);
cvtColor(result, result, COLOR_GRAY2BGR);
drawContours(result,contours,
-1, // draw all contours
new Scalar(0,0,255), // in blue
1); // with a thickness of 1
//Start to iterate to each contour founded
ListIterator<MatOfPoint> itc = contours.listIterator();
//Remove patch that are no inside limits of aspect ratio and area.
while (itc.hasNext())
{
//Create bounding rect of object
MatOfPoint mp = new MatOfPoint(itc.next().toArray());
Rect mr = boundingRect(mp);
rectangle(result,new Point(mr.x,mr.y),new Point(mr.x+mr.width,mr.y+mr.height),new Scalar(0,255,0));
Mat auxRoi=new Mat(img_threshold,mr);
if (OCR_verifySizes(auxRoi))
{
output.add(preprocessChar(auxRoi));
}
}
return output;`

Categories

Resources