so i have a 1024x1024 greyscale image, when i open this picture using matlab, matlab detect that the image is 1024x1024 uint8.
the problem is when I do image processing with android, where I divide the image into several parts, then do the attacking process to some parts of the image, then re-combine the image. then I open the image of the attacking result using matlab, and matlab detect image size 1024x1024x3 uint8. I've tried to change the image using the cvtColor function provided by opencv to change the image channel but the image is still considered 3 channel by matlab. this is a sample image before and after done image processing with android (left:before attacking, right:after attacking)
this is one of the attacking functions named gaussian noised which I implement using android
private Bitmap GaussianNoise(Bitmap src, double variance) {
Bitmap hasil = src;
Mat input = new Mat();
Mat imGray = new Mat();
Utils.bitmapToMat(src, input);
Imgproc.cvtColor(input, imGray, Imgproc.COLOR_RGBA2GRAY);
Mat noise = new Mat(imGray.size(), CvType.CV_64F);
Mat resultMat = new Mat();
Core.normalize(imGray, resultMat, 0.0, 1.0, Core.NORM_MINMAX, CV_64F);
Core.randn(noise, 0, Math.sqrt(variance));
Core.add(resultMat, noise, resultMat);
Core.normalize(resultMat, resultMat, 0.0, 1.0, Core.NORM_MINMAX, CV_64F);
resultMat.convertTo(resultMat, imGray.type(), 255, 0);
Utils.matToBitmap(resultMat, hasil);
return hasil;
}
all forms of assistance will be greatly appreciated
Related
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.
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 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;`
I'm using openCV for android to implement a logo detection algorithm. my goal now is to find a predefined logo in a picture I've taken with the android camera.
I can't get ANY right matches.. I think this is very weird considering I'm almost only using openCV library functions.
First I detect keypoints using FAST detector, my images are 500x500 in size
afterwards I use SURF to describe these keypoints.
with knn I ask for the 2 best matches, and elliminate those who don't have A ratio smaller than 0.6 (first.distance/ second.distance).
I'm getting around 10 matches, but they are all wrong, when I draw every match (100+), they all seem to be wrong
I can't see what I'm doing wrong here, does anyone have the same problem, or know what I'm doing wrong?
FeatureDetector FAST = FeatureDetector.create(FeatureDetector.FAST);
// extract keypoints
FAST.detect(image1, keypoints);
FAST.detect(image2, logoKeypoints);
DescriptorExtractor SurfExtractor = DescriptorExtractor
.create(DescriptorExtractor.SURF);
Mat descriptors = new Mat();
Mat logoDescriptors = new Mat();
SurfExtractor.compute(image1, keypoints, descriptors);
SurfExtractor.compute(image2, logoKeypoints, logoDescriptors);
List<DMatch> matches = new ArrayList<DMatch>();
matches = knn(descriptors, logoDescriptors);
Scalar blue = new Scalar(0, 0, 255);
Scalar red = new Scalar(255, 0, 0);
Features2d.drawMatches(image2, logoKeypoints, image1, keypoints,
matches, rgbout, blue, red);
I think the problem is the matcher you are using. For floatbased such as (SURF)descriptors use FLANN as a matcher or BRUTEFORCE as a matcher. Also strive to use the same feature descriptor for both extraction and matching...i.e SURF features on SURF keypoints.
Read this post on stackoverflow,and the articles linked in it for better understanding.
How Does OpenCV ORB Feature Detector Work?
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);