Get all the points in triangular ROI in a xy plane - matlab

Input: I have some 50000 points in a xy plane as shown in the below picture.
Now, I need to get all the possible points in a triangular ROI. How to get it. It can can be opencv or Matlab.
The below is the sample where I need to get the possible points of the triangular areas.

MATLAB has an inpolygon command: inpolygon.
For example, this code
xv = [0.1 0.4 0.15 0.1]; yv = [0 0.4 0.8 0];
x = rand(250,1); y = rand(250,1);
in = inpolygon(x,y,xv,yv);
plot(xv,yv,x(in),y(in),'r+',x(~in),y(~in),'bo')
generates a picture like this:

Something like this, in c++?
Mat plane = imread("plane.png"); // this is the 50 000 pixel plane image
// I assume your triangles are here. E.e. findContours function would save them here, but I don't know your situation.
vector<vector<Point> > triangles;
// this size is something like 1000, so here are only points that should be checkedd if they are inside some triangle
vector<Point> points;
// lets loop all rois and check if point is inside one of them
for (int j = 0; j < triangles.size(); j++) {
for (int i = 0; i < points.size(); i++) {
double test = pointPolygonTest(trigangles[j], points[i] false);
if (test < 0) {
cout << " point " << points[i] << " is outside of triangle " << j << endl;
} else if (test > 0) {
cout << " point " << points[i] << " is inside of triangle " << j << endl;
} else if (test == 0) {
cout << " point " << points[i] << " is on edge of triangle " << j << endl;
}
}
}
for more info: http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=pointpolygontest#pointpolygontest
here is OpenCV's example: http://docs.opencv.org/trunk/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.html

In OpenCV, you can quickly filter out the points that are not in the minimal bounding rectangle for each triangle. This rectangle can be previously computed by hand or with cv::boundingRect(). The hit test is done with Rect::contains(). This is a fast operation (at least much faster than cv::pointPolygonTest)and this will filter out the points that are obviously not in any triangle. Afterward, you test the points that pass the filter with cv::pointPolygonTest().
That is:
std::vector<cv::Point> pointList;
std::vector<cv::Rect> rectList;
std::vector<std::vector<Point>> triangleList;
for (int pointIndex = 0; pointIndex < pointList.size(); pointIndex++)
{
for (int rectIndex = 0; rectIndex < rectList.size(); rectIndex++)
{
if (!rectList[rectIndex].contains(pointList[pointIndex]))
continue;
if (cv::pointPolygonTest(triangleList[rectIndex], pointList[pointIndex], false) < 0)
continue;
/* TODO Mark the point for future use */
}
}

Related

Turning simple c algorithm into matlab

It's simple, I want to pick the biggest value of a line, make all other elements in a line equal to zero and then the position with the biggest value shall be transformed into 1.
This is the code:
float A [3][3];
A [0][0] = 1.1, A [0][1] = 3.2, A [0][2] = 1.3;
A [1][0] = 2.1, A [1][1] = 2.2, A [1][2] = 2.3;
A [2][0] = 3.1, A [2][1] = 3.2, A [2][2] = 3.3;
for (int i=0; i<3; i++) {
float biggest=-1000000;
int biggest_position=0;
for (int y=0; y<3; y++)
if (A [i][y]>biggest) {
biggest_position = y;
biggest = A[i][y];
cout << "biggest position" << biggest_position << endl;
}
for (int y=0; y<3; y++)
A [i][y] = 0;
A [i][biggest_position] = 1;
}
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
cout << A [i][j] << endl;
So what I need to do to rewrite properly this code in matlab language?
You can use max to find maximum, and create a all zero element matrix and put the max in first column of the matrix:
newA = zeros(size(A));
newA(:,1) = max(A,[],2);
Just do:
A = A==max(A); %array of zeros with only ones at the maximum of the columns of the array.
If you want the maximum of a row you transpose first using a '
A = (A'==max(A'))';
this may be what you want
a=[1,2,3;2,3,4;3,2,1;2,4,1]
[~,ap]= max(a,[],2);
atr=zeros(size(a))';
atr((1:size(a,1))*size(a,2)-size(a,2)+ap')=1;
atr'
and the result:
a =
1 2 3
2 3 4
3 2 1
2 4 1
ans =
0 0 1
0 0 1
1 0 0
0 1 0
it seems to be a more simple way by using matrix, you can try it

lapack tridiag - eigenvectors wrong sign

I'm using the lapack function tridiag to find the eigenvectors of the hamiltonian in a simulation of the infinite square well, and I seem to randomly get a wrong sign (for p=4 and 6 in this case) :
red is the theory and green the simulation
(they're also not normalized, but I think it's normal ?)
Here is the code :
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
extern "C"
void dsteqr_( char * , int *, double [], double [], double [], int *, double [],
int * ) ;
void tridiag( int n, double d[], double e[], double z[] )
/* Appel du sous-programme dsteqr de Lapack : calcul des valeurs et vecteurs
propres d'une matrice tridiagonale symmetrique */
{
int info ; // diagnostic
double work[2*n-2] ; // espace de travail
char compz='v' ; // mettre 'n' pour n'avoir que les valeurs propres
dsteqr_( &compz, &n, d, e, z, &n, work, &info ) ; // scalaires pointeurs
if ( info == 0 ) cout << "La diagonalisation s'est bien passée" << endl ;
else cout << "Attention ! SSTEQR : info =" << info << endl ;
}
double V(double x){
return 0;
}
int main() {
int n=100;
double d[n], e[n-1], z[n*n], x[n], v[n], L = 5, delta_x = L/n;
ofstream of1("eigenvalues.dat"), of2("eigenvectors.dat");
for(int i=0; i<n; i++){
for (int j=0; j<n; j++){
if (i == j) z[i+n*j] = 1;
else z[i+n*j] = 0;
}
x[i] = (i+0.5)*delta_x - 0.5*L;
v[i] = V(x[i]);
d[i] = 2/pow(delta_x, 2) + v[i];
if (i<n-2){
e[i] = -1/pow(delta_x, 2);
}
}
tridiag(n,d,e,z);
for (int i=0; i<n; i++){
of1 << d[i] << endl;
for (int j=0; j<n; j++){
of2 << z[i+n*j] << " ";
}
of2 << x[i] << endl;
}
of1.close();
of2.close();
return 0;
}
So does anyone know what is happening ?
The magnitude of your numerical result being larger than the magnitude of the reference result is due to the fact that L=5. The normalization of LAPACK would correspond to L=1. To get the correct vectors, divide all values by L !
Regarding the sign... If you change the signs of vectors in an orthonormal basis, the result is still an orthonormal basis. Moreover if A is an Hermitian matrix and if x is a vector so that A.x=l.x where l is a scalar, then A.(-x)=l.(-x). So the sign of the vector you get is not very significant... Moreover, if the matrix features many times the same eigenvalue, the result can contain any of the orthonormal basis of the subspace associated to this eigenvalue. For instance, if the matrix A is the identity, any orthonormal basis is an acceptable result for dsteqr().

MSER circles center

I`m using MSER feature detector to detect all
the circles from an image and it works perfect
but i have to get the center of those circles.
Do you know any posibility to get the center?
Here is the source code:
void main()
{
Mat inImg = imread(CProfilessuro1012Desktop1.bmp);
Mat textImg;
cvtColor(inImg, textImg, CV_BGR2GRAY);
vector vector Point contours;
vector Rect bboxes;
Ptr MSER mser = MSERcreate(22, (int)(0.00001textImg.colstextImg.rows), (int)(0.00015textImg.colstextImg.rows), 1, 1);
mser-detectRegions(textImg, contours, bboxes);
for(int i=0;i1;i++)
{ for(int j=0;jcontours[i].size();j++)
cout x=contours[i][j].x y=contours[i][j].y endl;
coutendl;
}
for (int i = 0; i bboxes.size(); i++)
{
cout x=bboxes[i].x y=bboxes[i].y endl;
rectangle(inImg, bboxes[i], CV_RGB(0, 255, 0));
}
cout contours[0].size()endl;
imshow(, inImg);
waitKey(0);
}
What I did:
float sumX = 0, sumY = 0;
int size = contours.size();
Point2f centroid;
if(size > 0){
for(int i=0;i<size;i++)
{
for(int j=0;j<contours[i].size();j++)
{
sumX += contours[i][j].x;
sumY += contours[i][j].y;
}
centroid.x = sumX/contours[i].size();
centroid.y = sumY/contours[i].size();
cout<<centroid.x<<" " <<centroid.y<<endl;
sumX=0;
sumY=0;
}
You can draw circles enclosing contours.
(x, y),radius = cv2.minEnclosingCircle(contour)
center = (int(x),int(y))
radius = int(radius)
For more Information, you can refer to https://docs.opencv.org/3.1.0/dd/d49/tutorial_py_contour_features.html

imregionalmax matlab function's equivalent in opencv

I have an image of connected components(circles filled).If i want to segment them i can use watershed algorithm.I prefer writing my own function for watershed instead of using the inbuilt function in OPENCV.I have successfu How do i find the regionalmax of objects using opencv?
I wrote a function myself. My results were quite similar to MATLAB, although not exact. This function is implemented for CV_32F but it can easily be modified for other types.
I mark all the points that are not part of a minimum region by checking all the neighbors. The remaining regions are either minima, maxima or areas of inflection.
I use connected components to label each region.
I check each region for any point belonging to a maxima, if yes then I push that label into a vector.
Finally I sort the bad labels, erase all duplicates and then mark all the points in the output as not minima.
All that remains are the regions of minima.
Here is the code:
// output is a binary image
// 1: not a min region
// 0: part of a min region
// 2: not sure if min or not
// 3: uninitialized
void imregionalmin(cv::Mat& img, cv::Mat& out_img)
{
// pad the border of img with 1 and copy to img_pad
cv::Mat img_pad;
cv::copyMakeBorder(img, img_pad, 1, 1, 1, 1, IPL_BORDER_CONSTANT, 1);
// initialize binary output to 2, unknown if min
out_img = cv::Mat::ones(img.rows, img.cols, CV_8U)+2;
// initialize pointers to matrices
float* in = (float *)(img_pad.data);
uchar* out = (uchar *)(out_img.data);
// size of matrix
int in_size = img_pad.cols*img_pad.rows;
int out_size = img.cols*img.rows;
int x, y;
for (int i = 0; i < out_size; i++) {
// find x, y indexes
y = i % img.cols;
x = i / img.cols;
neighborCheck(in, out, i, x, y, img_pad.cols); // all regions are either min or max
}
cv::Mat label;
cv::connectedComponents(out_img, label);
int* lab = (int *)(label.data);
in = (float *)(img.data);
in_size = img.cols*img.rows;
std::vector<int> bad_labels;
for (int i = 0; i < out_size; i++) {
// find x, y indexes
y = i % img.cols;
x = i / img.cols;
if (lab[i] != 0) {
if (neighborCleanup(in, out, i, x, y, img.rows, img.cols) == 1) {
bad_labels.push_back(lab[i]);
}
}
}
std::sort(bad_labels.begin(), bad_labels.end());
bad_labels.erase(std::unique(bad_labels.begin(), bad_labels.end()), bad_labels.end());
for (int i = 0; i < out_size; ++i) {
if (lab[i] != 0) {
if (std::find(bad_labels.begin(), bad_labels.end(), lab[i]) != bad_labels.end()) {
out[i] = 0;
}
}
}
}
int inline neighborCleanup(float* in, uchar* out, int i, int x, int y, int x_lim, int y_lim)
{
int index;
for (int xx = x - 1; xx < x + 2; ++xx) {
for (int yy = y - 1; yy < y + 2; ++yy) {
if (((xx == x) && (yy==y)) || xx < 0 || yy < 0 || xx >= x_lim || yy >= y_lim)
continue;
index = xx*y_lim + yy;
if ((in[i] == in[index]) && (out[index] == 0))
return 1;
}
}
return 0;
}
void inline neighborCheck(float* in, uchar* out, int i, int x, int y, int x_lim)
{
int indexes[8], cur_index;
indexes[0] = x*x_lim + y;
indexes[1] = x*x_lim + y+1;
indexes[2] = x*x_lim + y+2;
indexes[3] = (x+1)*x_lim + y+2;
indexes[4] = (x + 2)*x_lim + y+2;
indexes[5] = (x + 2)*x_lim + y + 1;
indexes[6] = (x + 2)*x_lim + y;
indexes[7] = (x + 1)*x_lim + y;
cur_index = (x + 1)*x_lim + y+1;
for (int t = 0; t < 8; t++) {
if (in[indexes[t]] < in[cur_index]) {
out[i] = 0;
break;
}
}
if (out[i] == 3)
out[i] = 1;
}
The following listing is a function similar to Matlab's "imregionalmax". It looks for at most nLocMax local maxima above threshold, where the found local maxima are at least minDistBtwLocMax pixels apart. It returns the actual number of local maxima found. Notice that it uses OpenCV's minMaxLoc to find global maxima. It is "opencv-self-contained" except for the (easy to implement) function vdist, which computes the (euclidian) distance between points (r,c) and (row,col).
input is one-channel CV_32F matrix, and locations is nLocMax (rows) by 2 (columns) CV_32S matrix.
int imregionalmax(Mat input, int nLocMax, float threshold, float minDistBtwLocMax, Mat locations)
{
Mat scratch = input.clone();
int nFoundLocMax = 0;
for (int i = 0; i < nLocMax; i++) {
Point location;
double maxVal;
minMaxLoc(scratch, NULL, &maxVal, NULL, &location);
if (maxVal > threshold) {
nFoundLocMax += 1;
int row = location.y;
int col = location.x;
locations.at<int>(i,0) = row;
locations.at<int>(i,1) = col;
int r0 = (row-minDistBtwLocMax > -1 ? row-minDistBtwLocMax : 0);
int r1 = (row+minDistBtwLocMax < scratch.rows ? row+minDistBtwLocMax : scratch.rows-1);
int c0 = (col-minDistBtwLocMax > -1 ? col-minDistBtwLocMax : 0);
int c1 = (col+minDistBtwLocMax < scratch.cols ? col+minDistBtwLocMax : scratch.cols-1);
for (int r = r0; r <= r1; r++) {
for (int c = c0; c <= c1; c++) {
if (vdist(Point2DMake(r, c),Point2DMake(row, col)) <= minDistBtwLocMax) {
scratch.at<float>(r,c) = 0.0;
}
}
}
} else {
break;
}
}
return nFoundLocMax;
}
I do not know if it is what you want, but in my answer to this post, I gave some code to find local maxima (peaks) in a grayscale image (resulting from distance transform).
The approach relies on subtracting the original image from the dilated image and finding the zero pixels).
I hope it helps,
Good luck
I had the same problem some time ago, and the solution was to reimplement the imregionalmax algorithm in OpenCV/Cpp. It is not that complicated, because you can find the C++ source code of the function in the Matlab distribution. (somewhere in toolbox). All you have to do is to read carefully and understand the algorithm described there. Then rewrite it or remove the matlab-specific checks and you'll have it.

Hashing 2D, 3D and nD vectors

What are good hashing functions (fast, good distribution, few collisions) for hashing 2d and 3d vectors composed of IEEE 32bit floats. I assume general 3d vectors, but algorithms assuming normals (always in [-1,1]) are also welcome. I also do not fear bit-manipulation as IEEE floats are alsways IEEE floats.
Another more general problem is hashing an Nd float-vector, where N is quite small (3-12) and constant but not known at compile time. At the moment I just take these floats as uints and XOR them together, which is probably not the best solution.
There's a spatial hash function described in Optimized Spatial Hashing for Collision Detection of Deformable Objects. They use the hash function
hash(x,y,z) = ( x p1 xor y p2 xor z
p3) mod n
where p1, p2, p3 are large
prime numbers, in our case 73856093,
19349663, 83492791, respectively. The
value n is the hash table size.
In the paper, x, y, and z are the discretized coordinates; you could probably also use the binary values of your floats.
I have two suggestions.
Assume a grid cell of size l and quantize the x, y and z co-ordinates by computing ix = floor(x/l), iy = floor(y/l), and iz = floor(z/l), where ix, iy and iz are integers. Now use the hash function defined in Optimized Spatial Hashing for Collision Detection of Deformable Objects
If you don't do the quantization, it wont be sensitive to closeness(locality).
Locality Sensitive Hashing has been mentioned for hashing higher dimensional vectors. Why not use them for 3d or 2d vectors as well? A variant of LSH using adapted for Eucledian distance metric (which is what we need for 2d and 3d vectors) is called Locality Sensitive Hashing using p-stable distributions. A very readable tutorial is here.
I wrote this in Python based on the comments seen here,
l = 5
n = 5
p1,p2,p3 = 73856093, 19349663, 83492791
x1 = [33,4,11]
x2 = [31,1,14]
x3 = [10,44,19]
def spatial_hash(x):
ix,iy,iz = np.floor(x[0]/l), np.floor(x[1]/l), np.floor(x[2]/l)
return (int(ix*p1) ^ int(iy*p2) ^ int(iz*p3)) % n
print (spatial_hash(x1))
print (spatial_hash(x2))
print (spatial_hash(x3))
It gives
1
1
3
It seemed to work.
In C++
#include <cstdlib>
#include <iostream>
#include <unordered_map>
#include <vector>
#include <random>
#include <eigen3/Eigen/Dense>
using namespace Eigen;
using namespace std;
const int HASH_SIZE = 200;
//const float MAX = 500.0;
const float L = 0.2f;
const float mmin = -1.f;
const float mmax = 1.f;
unordered_map<int, vector<Vector3d>> map ;
inline size_t hasha(Vector3d &p) {
int ix = (unsigned int)((p[0]+2.f) / L);
int iy = (unsigned int)((p[1]+2.f) / L);
int iz = (unsigned int)((p[2]+2.f) / L);
return (unsigned int)((ix * 73856093) ^ (iy * 19349663) ^ (iz * 83492791)) % HASH_SIZE;
}
int main(int argc, char** argv) {
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(-1.0,1.0);
for(size_t i=0;i<300;i++){
float x = distribution(generator);
float y = distribution(generator);
float z = distribution(generator);
Vector3d v(x,y,z);
std::cout << hasha(v) << " " << v[0] << " " << v[1] << " " << v[2] << std::endl;
map[hasha(v)].push_back(v);
vector<Vector3d> entry = map[hasha(v)];
std::cout << "size " << entry.size() << std::endl;
}
for (const auto & [ key, value ] : map) {
cout << key << std::endl;
vector<Vector3d> v = map[key];
float average = 0.0f;
for (int i=0; i<v.size(); i++){
for (int j=0; j<v.size(); j++){
if (i!=j){
Vector3d v1 = v[i];
Vector3d v2 = v[j];
std::cout << " dist " << (v1-v2).norm() << std::endl;
}
}
}
}
}