B4A Library OpenCV 3.x

JordiCP

Expert
Licensed User
Longtime User
Start OffTopic:
Sub OffTopic_Resume

' Please make sure that topic has been previously loaded​
  • I imagine that they have a really huge database continuously trained with features of every object, so I also suppose that OpenCV or similar must be somewhere in the middle, with a lot of algorithms running on it.
  • Related to the offTopic, the other day someone talked me about Pinterest Lens, I suppose the idea behind is similar. Also, google image search must use some kind of feature-based search....
  • There are so many things that can be done...if one had enough time for it
End Sub
 

padvou

Active Member
Licensed User
Longtime User
Maybe they are crowling the entire net for images and their descriptions, who knows?
 

JordiCP

Expert
Licensed User
Longtime User
The goal is to detect the position of the center of the circle in the panel, so that I can take the X and Y coordinates for further use.
I have added the "imageManipulations2" example, adding your picture, and an option (the last checkbox) to detect circles using Hough transforms. The rest of the options will do nothing when you enable the last one (check code) , but they are good for learning
You will see that it works ok for your image, and there are some "false positives" for the other two, which don't have "real" circles. That's how detection works, you tune de image and parameters based on what you already know of it, in order to "help" the algorithm as much as possible.
Also, in case of some detectors (as the Hough transform here), depending on the parameters used, the algorithm will not "come back" for many seconds
(Take into account that the full example is only expecting 640x480 source images, so it may crash if you feed it with other resolutions.)
 

Attachments

  • imageManipulations2.zip
    341.6 KB · Views: 404

padvou

Active Member
Licensed User
Longtime User

That's a great example!
However, how do I detect the circles when they exist on another image?
Here's an example image attached, where I would like to detect the position of the circles as you do in the imagemanipulations2 and log the circle coordinates.
Also, why only 640x480?
 

Attachments

  • Capture.PNG
    439.8 KB · Views: 257

JordiCP

Expert
Licensed User
Longtime User
Hi,

In fact the 640x480 was a limitation of the example, since the images were loaded and converted to a mutable bitmap. Now it dows not have this limitation.

I have made it to work with your other sample picture. But I have had to tune the parameters for HoughCircle function. The circle is drawn and coordinates written to the log.
Note that there is not a "magic call" that will detect always what you want, because in the same image there are "sets of points" that an algorithm "could think" that are circles. You can play with the parameters and you will see that it detects other circles, even if they are not such, or doesn't detect anything. That is what I told you that algorithms need 'clues'.
See THIS for a reference on the used function

Just a thought, if the circles in the image will always be that logo, even if it is with different sizes and positions, perhaps you could use other approaches...
 

Attachments

  • imageManipulations3.zip
    444.4 KB · Views: 356

padvou

Active Member
Licensed User
Longtime User

Thank you very much for the example. It really helped me, because it fits with what I have in mind, so it's easier for me to understand.
How do you deal with concentric circles? I find this parameter: "minDist – Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed." to not be able to set it to 0.
 

JordiCP

Expert
Licensed User
Longtime User
I would try with mindist=1 for concentric circles, I don't know if it accepts 0, you can test it.
Anyway, the HoughCircles function is using HOUGH_GRADIENT method (it is one of the parameters), since it is the only one implemented in the android version. So, it means that it works with Canny ( convert to grayscale and then apply canny operator to detect edges). It means that it does not take into account color information.

Again, if you know particularities of the circles that you want to find (background color , circle color, maximum size, if there is always more than one since they are concentric....) you can tune your algorithm to improve its "detection rate". Not only by function parameters, but also "preprocessing" your image according to this info.
 

padvou

Active Member
Licensed User
Longtime User

I have added some seekbars in the project you uploaded, so I can try some tuning in real time and not load and reload the project.
However, I find that tuning may work for a specific image but since I will not be able to know in my application, the exact size of the circles, it will either not detect them at all, detect them partially or have false positives.
So if there is no better approach, I think I should move to image detection and not circle detection.
What do you think?
 

JordiCP

Expert
Licensed User
Longtime User
So if there is no better approach, I think I should move to image detection and not circle detection.
That was one of the reasons of my previous questions .
Circle detection may work directly (without tuning) only for 'lab' images. If all your images will have the white logo with the concentric circles and this is what you are looking for, then you could try image detection or even another approach: detecting white blobs, then check if their boundings are more or less square, and run the circle detection only on that subregion (or even better, assume that the circle center will be near the center of that square).
 

padvou

Active Member
Licensed User
Longtime User


Image detection is that thing with the XML files, right?
A fellow suggested a procedure some posts ago in order to create them.
Is one of this thread's examples relative to this? Does this way work even if the image to be detected is proportionally resized to the original?
 

JordiCP

Expert
Licensed User
Longtime User
If the image to be found is always the same, but scaled in different positions, you could also try multiscale template matching.

Is the image to be detected always the same?
 

padvou

Active Member
Licensed User
Longtime User
If the image to be found is always the same, but scaled in different positions, you could also try multiscale template matching.

Is the image to be detected always the same?
Well,
To be exact, I have to detect three images and find out the distances between them. But to answer your question, yes basically they are always the same.
 

padvou

Active Member
Licensed User
Longtime User
Well,
To be exact, I have to detect three images and find out the distances between them. But to answer your question, yes basically they are always the same.

I 've figured out that it must be this. Could you please help me with the B4A code?
 

biometrics

Active Member
Licensed User
Longtime User
Hi Jordi,

I'm trying to port my Windows OpenCV app to Android. I need some help with the following two issues:

1. After using detectMultiScale to find faces I want access to the mat of a face. In C++ I do the following:

B4X:
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(iFaceWidth, iFaceHeight));
for( int i = 0; i < faces.size(); i++ ) {
  Mat faceROI = frame_gray( faces[i] );

In B4A I can't figure out how to access it, so far I've got:

B4X:
Dim frame_gray As OCVMat
Dim faces As OCVMatOfRect
Dim facesArray() As OCVRect
Dim faceROI As OCVMat

libOpenCvFaceCascade.detectMultiScale(frame_gray, faces, dScaleFactor, iMinimumNeighbours, iHaarScaleImage, minimumSize, maximumSize)  
facesArray = faces.toArray
  
For iFaceIndex = 0 To facesArray.Length - 1
  faceROI = facesArray(iFaceIndex).clone

The last line produces and error:

B4X:
faceROI = facesArray(iFaceIndex).clone
javac 1.8.0_131
src\isenzo\audiencemeasurement\main.java:517: error: incompatible types: Rect cannot be converted to Mat
mostCurrent._faceroi = (com.appiotic.ocv4b4a.core.Mat)(_facesarray[_ifaceindex].clone());

I can see it's the wrong type but how do I access the detected faces mats?

2. I'm looking for the OpenCV FastMatchTemplate function. Where can I find it?

Thanks a lot, this is an awesome library.
 

biometrics

Active Member
Licensed User
Longtime User
I've changed the clone line to:

B4X:
faceROI = faces.submat(facesArray(iFaceIndex).y, facesArray(iFaceIndex).y + facesArray(iFaceIndex).height, facesArray(iFaceIndex).x, facesArray(iFaceIndex).x + facesArray(iFaceIndex).width)

and I'm now getting this error:

B4X:
CvException [com.appiotic.ocv4b4a.core.CvException: cv::Exception: C:/Develop/git/opencv_320/modules/core/src/matrix.cpp:483: error: (-215) 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows in function cv::Mat::Mat(const cv::Mat&, const cv::Range&, const cv::Range&)
 

JordiCP

Expert
Licensed User
Longtime User
I suppose that you want to get a ROI of the original picture, that is frame_gray. This is not what you are doing in code

'faces' is an OCVMat, more precisely an OCVMatOfRect. It contains the OCVRects that it has detected. So you can get the rectangles from here in order to have the ROIs that you want from the original image
B4X:
faceROI = frame_gray.submat(facesArray(iFaceIndex).y, facesArray(iFaceIndex).y + facesArray(iFaceIndex).height, facesArray(iFaceIndex).x, facesArray(iFaceIndex).x + facesArray(iFaceIndex).width)

faceROI will be a subMat of the original. Whatever you do to it, will be done to the original. So, if you need a copy you must do (not tested)
B4X:
Dim faceROIcloned as OCVMat
faceROIcloned = faceROI.clone()
 

biometrics

Active Member
Licensed User
Longtime User

Thanks Jordi.

As to my second question, where can I find the FastMatchTemplate function?
 

JordiCP

Expert
Licensed User
Longtime User
Thanks Jordi.
As to my second question, where can I find the FastMatchTemplate function?
You won't believe, but I don't know . On one side, Android version of OpenCV does not include all the features available in C++. The second reason is that I have never used it (but would like to test it soon)

Anyway, you can try with
B4X:
Dim mImgProc as OCVImgProc
mImgProc.matchTemplate(.....)
...but I am not sure if it only works with parts of the image that are of the same size, so it will only be valid for still pictures.
If this is not the case and you are working with the camera (so the object that you want to find will not have the same dimensions and the above does not fit your needs), then you should look at features2D and descriptors derived classes. It implements matching methods that are based on invariant descriptors, so it makes them suitable for 'real time' images.


I am also willing to experiment with it, but won't have time till next week . Besides, I think that @padvou question above could be solved using this.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…