I'm working with sift using opencv sdk for android
I'm facing difficulties in drawing matches between two images using the
Feature2d.drawMatches()
whenever I run the app it goes through all the steps but stopped when reaching the draw function.
Here's the full code:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("opencv_java");
System.loadLibrary("nonfree");
}
private ImageView imageView;
private FeatureDetector detector = FeatureDetector.create(FeatureDetector.SIFT);
DescriptorExtractor descriptorExtractor=DescriptorExtractor.create(DescriptorExtractor.SIFT);
DescriptorMatcher descriptorMatcher= DescriptorMatcher.create(3);
Bitmap inputImage;
Bitmap inputImage2;
Bitmap out;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(OpenCVLoader.initDebug()){
Toast.makeText(this,"Hiii",Toast.LENGTH_SHORT).show();}
inputImage = BitmapFactory.decodeResource(getResources(), R.drawable.object);
inputImage2 = BitmapFactory.decodeResource(getResources(), R.drawable.objecttest);
out = BitmapFactory.decodeResource(getResources(), R.drawable.test);
imageView = (ImageView) this.findViewById(R.id.imageView);
sift();
}
public void onResume() {
super.onResume();
}
public void sift() {
Mat rgba = new Mat();
Mat rgba2 = new Mat();
Mat desc=new Mat();
Mat desc2=new Mat();
MatOfDMatch matches=new MatOfDMatch();
Mat output=new Mat();
Utils.bitmapToMat(inputImage, rgba);
Utils.bitmapToMat(inputImage2, rgba2);
Utils.bitmapToMat(out, output);
MatOfKeyPoint keyPoints = new MatOfKeyPoint();
MatOfKeyPoint keyPoints2 = new MatOfKeyPoint();
Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGBA2GRAY);
Imgproc.cvtColor(rgba2, rgba2, Imgproc.COLOR_RGBA2GRAY);
detector.detect(rgba, keyPoints);
detector.detect(rgba2, keyPoints2);
descriptorExtractor.compute(rgba,keyPoints,desc);
descriptorExtractor.compute(rgba2,keyPoints2,desc2);
descriptorMatcher.match(desc,desc2,matches);
Features2d.drawMatches(rgba,keyPoints,rgba2,keyPoints2,matches,output);
Utils.matToBitmap(output, out);
imageView.setImageBitmap(out);
}
}
I also need to know whether sift is the best choice for the use of detecting complicated objects in real time?
Edit 1: I notice now that I'm getting the following errors
OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows)
Fatal signal 11 (SIGSEGV), code 2, fault addr 0x12ce08e0 in tid 9971
Problem solved:
the error I've mentioned was preventing the image from being displayed for some reason( maybe the difference of properties between the image view and the image we want to display let's say the dimensions in some cases
actually I'm not sure about the previous point but it was mentioned out there, and the solution was to set the image view to be dynamically resized according to the image but that didn't work for me)
My problem was solved by replacing these instructions:
Features2d.drawMatches(rgba,keyPoints,rgba2,keyPoints2,matches,output);
Utils.matToBitmap(output, out);
imageView.setImageBitmap(out);
with the following:
Scalar RED = new Scalar(255,0,0);
Scalar GREEN = new Scalar(0,255,0);
MatOfByte drawnMatches = new MatOfByte();
Features2d.drawMatches(rgba,keyPoints,rgba2,keyPoints2,matches,output,GREEN, RED, drawnMatches, Features2d.NOT_DRAW_SINGLE_POINTS);
Bitmap imageMatched = Bitmap.createBitmap(output.cols(), output.rows(), Bitmap.Config.RGB_565);//need to save bitmap
Utils.matToBitmap(output, imageMatched);
imageView.setImageBitmap(imageMatched);
I didn't actually get the difference, so further help describing this will be so helpful, but hope this can temporarily help people having the same problem
Related
So I have been trying to get coordinates of the corner in a QR 1.
But the output from detectAndDecode functions return some string that looks like "[D#fb258ec".
What have I done wrong? Or is the vertices not meant what I think they mean?
Just starting out on the journey to learn openCV and Android, the process has been though...
Any help or advice is much appreciated, thanks.
A snippet of what I think is the main part is shown below.
Edit 1: Added link to QR and more code.
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
mat1 = inputFrame.gray();
Mat clrCrr = new Mat();
Imgproc.cvtColor(mat1, clrCrr, Imgproc.COLOR_GRAY2BGR);
QRCodeDetector decoder = new QRCodeDetector();
Mat QR = new Mat(); //Mat for QR code
Mat points = new Mat(); // points of QR Mat
Mat dst = new Mat(); //Output frame
runOnUiThread(new Runnable() {
public void run() {
Handler h = new Handler();
String data = decoder.detectAndDecode(clrCrr, points,QR); //Decode QR
EditText editText = findViewById(R.id.editText);
points.convertTo(points,CvType.CV_64FC3);
editText.setText("Point 1 " +points.get(0,0) );
Log.d("Test", String.valueOf(points.get(0,1)));
h.postDelayed(this,3000);
}
});
Imgproc.threshold(mat1, dst, 100, 200, Imgproc.THRESH_BINARY); // Threshold and return dst
return dst
}
I think I found the solution.
Just need to use
Arrays.toString(points.get(0,0))
instead of just
points.get(0,0)
This will then return a coordinates like [1142.0, 230.0]
I am developing one Android application using OpenCV where I have to implement Background Subtraction. I am able to see some frames in grayscale and background removed, it only lasts for a while though, and then the application crashes.
Technique used: BackgroundSubtractorMOG2
This is my snippet of OnCameraFrame
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
Mat frame = inputFrame.rgba();
Mat mRgb = new Mat();
Mat mFGMask = new Mat();
BackgroundSubtractorMOG2 mog2 = Video.createBackgroundSubtractorMOG2();
Imgproc.cvtColor(frame, mRgb, Imgproc.COLOR_RGBA2RGB);
mog2.apply(mRgb, mFGMask);
Imgproc.cvtColor(mFGMask, frame, Imgproc.COLOR_GRAY2RGBA);
return frame;
}
Thanks in advance.
I was able to solve my issue.
new Mat() which is used was causing an issue of memory management. It has to be initialized just once in onCameraViewStarted and the returning Mat has to be released in onCameraViewStopped. After modifying the code as per suggestions through the OpenCV community, I was able to execute my application properly.
1. Declare at the first
private Mat mRgb;
private Mat mFGMask;
private Mat frame;
private BackgroundSubtractorMOG2 mog2;
Initialize in onCameraViewStarted
public void onCameraViewStarted(int width, int height) {
mRgb = new Mat();
mFGMask = new Mat();
mog2 = Video.createBackgroundSubtractorMOG2();
}
Release the returning frame in onCameraViewStopped
public void onCameraViewStopped() {
frame.release();
}
For full code: https://github.com/rishirajrsawant/OpenCV-Background-Subtraction
I am using OpenCV android library thresholding method for image segmentation, but the problem is that the output bitmap contains black background which I do not want please note that original image does not have any black background it is actually white. I am attaching the code for your reference, I am new to opencv and don't have much understanding about it also so kindly help me out.
private void Segmentation() {
Mat srcMat = new Mat();
gray = new Mat();
Utils.bitmapToMat(imageBmp, srcMat);
Imgproc.cvtColor(srcMat, gray, Imgproc.COLOR_RGBA2GRAY);
grayBmp = Bitmap.createBitmap(imageBmp.getWidth(), imageBmp.getHeight(), Bitmap.Config.RGB_565);
Utils.matToBitmap(gray, grayBmp);
grayscaleHistogram();
Mat threshold = new Mat();
Imgproc.threshold(gray, threshold, 0, 255, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU);
thresBmp = Bitmap.createBitmap(imageBmp.getWidth(), imageBmp.getHeight(), Bitmap.Config.RGB_565);
Utils.matToBitmap(threshold, thresBmp);
Mat closing = new Mat();
Mat kernel = Mat.ones(5, 5, CvType.CV_8U);
Imgproc.morphologyEx(threshold, closing, Imgproc.MORPH_CLOSE, kernel, new Point(-1, -1), 3);
closingBmp = Bitmap.createBitmap(imageBmp.getWidth(), imageBmp.getHeight(), Bitmap.Config.RGB_565);
Utils.matToBitmap(closing, closingBmp);
result = new Mat();
Core.subtract(closing, gray, result);
Core.subtract(closing, result, result);
resultBmp = Bitmap.createBitmap(imageBmp.getWidth(), imageBmp.getHeight(), Bitmap.Config.RGB_565);
Utils.matToBitmap(result, resultBmp);
Glide.with(ResultActivity.this).asBitmap().load(resultBmp).into(ivAfter);
}
enter image description here
What exactly do you want it to be then? Binary thresholding works like this:
if value < threshold:
value = 0
else:
value = 1
Of course you can convert it to a grayscale / RGB image and adjust the background to your liking. You can also invert your image (white background, black segmentation) by using the ~ operator.
segmented_image = ~ segmented_image
Edit: OpenCV has a dedicated flag to invert the results: CV_THRESH_BINARY_INV You are already using it, maybe try changing it to CV_THRESH_BINARY
I have an image composed of 3 objects and I need to extract those objects. I tried Watershed algorithm but it doesn't work as expected.
i don't have a good understanding of how this algorithm work so I can't figure out the real problem.
Here is my code
public Mat steptowatershed(Mat img)
{
Mat threeChannel = new Mat();
Imgproc.cvtColor(img, threeChannel, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(threeChannel, threeChannel, 0, 255, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU);
Mat fg = new Mat(img.size(),CvType.CV_8U);
Imgproc.erode(threeChannel,fg,new Mat());
Mat bg = new Mat(img.size(),CvType.CV_8U);
Imgproc.dilate(threeChannel,bg,new Mat());
Imgproc.threshold(bg,bg,1, 128,Imgproc.THRESH_BINARY_INV);
Mat markers = new Mat(img.size(),CvType.CV_8U, new Scalar(0));
Core.add(fg, bg, markers);
Mat result1= new Mat();
Imgproc.cvtColor(img, img, Imgproc.COLOR_BGRA2BGR);
WatershedSegmenter segmenter = new WatershedSegmenter();
segmenter.setMarkers(markers);
result1 = segmenter.process(img);
return result1;
}
public class WatershedSegmenter
{
public Mat markers=new Mat();
public void setMarkers(Mat markerImage)
{
markerImage.convertTo(markers, CvType.CV_32SC1);
}
public Mat process(Mat image)
{
Imgproc.watershed(image,markers);
markers.convertTo(markers,CvType.CV_8U);
return markers;
}
}
Here is the original image
Here is the result image
I need the extract all 3 objects later.
I wish you guys help me solve this issue.
When capturing frames with the camera in my Android app the images contain a lot of noise.
Here are 3 frames i have captured with my device if you look at the on the right of these frames you see that every frame has this dark gray noise. I need the frames to be the same if that is possible.
Does anyone know where this noise is coming from and more important how to get rid of it?
#Override
public void onFocus(byte[] data) {
frame = data;
processFrame();
}
private void processFrame() {
int height = mCameraPreview.getFrameHeight();
int width = mCameraPreview.getFrameWidth();
Mat mYuv = new Mat( height + height/2, width, CvType.CV_8UC1 );
mYuv.put( 0, 0, frame );
Mat mRgba = new Mat();
Imgproc.cvtColor( mYuv, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4 );
filter.apply(mRgba);
}
In my filter method I make use of OpenCV template matching to find this specific part of the image. The objectDetected method saves the result as an image.
#Override
public void apply(Mat src) {
Mat match = templateMatch(src, template1, 0.07);
if(match != null){
Mat match2 = templateMatch(match, template2, 0.04);
if(match2 != null){
Mat gray = new Mat(match2.size(), CvType.CV_8U);
Imgproc.cvtColor(match2, gray, Imgproc.COLOR_BGR2GRAY);
objectDetectedListener.objectDetected(gray, "frame");