How to construct keyline in opencv if only the end points of the line are available? - opencv

Opencv provides a structure called keyline, which is detected by line segment detectors. The structure has various public members such as angle, length etc.
The following class members are not clearly explained such as class_id, endPointX, endPointY, ePointInOctaveX, ePointInOctaveY, octave, startPointX, startPointY etc.
My questions is if I have the end points of the line, can the structure members of keyline be constructed?
cv::Point P1 (0,0);
cv::Point P2 (10,10);
cv::line_descriptor::KeyLine L; // How to construct L from P1 and P2?
L.octave = ??;
L.endPointX = ??;
L.endPointY = ??;
L.ePointInOctaveX = ??;
L.ePointInOctaveY = ??;
L.startPointX = ??;
L.startPointY = ??

Related

Vectorization issue

Say you have two column vectors vv and ww, each with 7 elements (i.e., they have dimensions 7x1). Consider the following code:
z = 0;
for i = 1:7
z = z + v(i) * w(i)
end
A) z = sum (v .* w);
B) z = w' * v;
C) z = v * w;
D) z = w * v;
According to the solutions, answers (A) AND (B) are the right answers, can someone please help me understand why?
Why is z = v * w' which is similar to answer (B) but only the order of the operation changes, is false? Since we want a vector that by definition only has one column, wouldn't we need a matrix of this size: 1x7 * 7x1 = 1x1 ? So why is z = v' * w false ? It gives the same dimension as answer (B)?
z = v'*w is true and is equal to w'*v.
They both makes 1*1 matrix, which is a number value in octave.
See this:
octave:5> v = rand(7, 1);
octave:6> w = rand(7, 1);
octave:7> v'*w
ans = 1.3110
octave:8> w'*v
ans = 1.3110
octave:9> sum(v.*w)
ans = 1.3110
Answers A and B both perform a dot product of the two vectors, which yields the same result as the code provided. Answer A first performs the element-wise product (.*) of the two column vectors, then sums those intermediate values. Answer B performs the same mathematical operation but does so via a dot product (i.e., matrix multiplication).
Answer C is incorrect because it would be performing a matrix multiplication on misaligned matrices (7x1 and 7x1). The same is true for D.
z = v * w', which was not one of the options, is incorrect because it would yield a 7x7 matrix (instead of the 1x1 scalar value desired). The point is that order matters when performing matrix multiplication. (1xN)X(Nx1) -> (1x1), whereas (Nx1)X(1xN) -> (NxN).
z = v' * w is actually a correct solution but was simply not provided as one of the options.

optimal thresholding for extract hand image

I am working on palm print identification by palm texture and geometry. i want to binarized hand image in preprocessing step for extracting geometry features like palm width and finger width.
i have used Gaussian filter for reduced noise and Otsu method for thresholding but I could not reach Optimal image! i was wondering if someone help me!
my database downloaded from "IIT Delhi Touch-less Palm print "
I=imread('hand.jpg');
h= fspecial('gaussian', 15,5);
s=imfilter(I,h,'symmetric');
q=graythresh(I)
BW=im2bw(I,q);
I have tried the following code and getting some promising result on your dropbox images. you can try it and share your results for further approach.
clc
clear all
close all
impath = 'E:\GoogleDrive\Mathworks\irisDEt\HandSeg';
[name,path] = uigetfile({'*.jpg';'*.png'},'mytitle',impath);
im =imread([path,name]);
im = imresize(im,0.5);
gms = 15;
red = im(:,:,1);
redmed = medfilt2(red,[gms,gms],'symmetric');
redmedbw = im2bw(redmed,0.9*graythresh(redmed));
redmedbw = bwareaopen(redmedbw,1500);
redmedbw = imclose(redmedbw,strel('disk',5));
figure,imshow(im,[])
figure,imshow(redmed,[])
figure,imshow(redmedbw,[])
My results are:
Code for signature estimation of the structure and extraction on critical(peaks and vallys) from the structure:
function [sig,xysamp,idx]= signature(bw,prec)
boundry = bwboundaries(bw);
xy = boundry{1};
x = xy(:,1);
y = xy(:,2);
len = length(x);
res = (len/prec);
re = rem(res,2);
if re
res = ceil(res);
end
indexes = 1:res:len;
xnew = x(indexes);
ynew = y(indexes);
xysamp = [xnew,ynew] ;
cx = round(mean(xnew));
cy = round(mean(ynew));
xn = abs(xnew-cx);
yn = abs(ynew-cy);
% ang = atand(yn./xn);
sig = (xn.^2+yn.^2);
sig = sig/max(sig);
% Critical Points in Signatures.
diffsig = diff(sig);
% pos = zeros(length(diffsig),1);
idx = 1;
for i = 2:length(diffsig)
if diffsig(i-1)*diffsig(i) <0
idx = [idx,i];
end
end
idx = [idx,i];
Here idx are the indexes of xysamp which gives actual boundry location in the image. the location of peaks and vallys may not be exact as i m doing sampling of boundry and it is a very simple way to approach the structural based problems.
Thank You
Result of critical point extraction:

Intersection between two lines as defined by points without extending lines

I know there are various posts on stackoverflow about given two lines defined by two points each, being able to calculate the intersection, but typically those solutions extend the lines as opposed to treating their physical sizes.
Background search: The typical function used to calculate the intersection of two lines as defined by points is shown below, but credit goes to here.
// Finds the intersection of two lines, or returns false.
// The lines are defined by (o1, p1) and (o2, p2).
bool intersection(Point2f o1, Point2f p1, Point2f o2, Point2f p2,
Point2f &r)
{
Point2f x = o2 - o1;
Point2f d1 = p1 - o1;
Point2f d2 = p2 - o2;
float cross = d1.x*d2.y - d1.y*d2.x;
if (abs(cross) < /*EPS*/1e-8)
return false;
double t1 = (x.x * d2.y - x.y * d2.x)/cross;
r = o1 + d1 * t1;
return true;
}
Problem: While this code works phenomenally, I am wondering if anyone knows how to alter this function where if the lines as defined by the points do not physically intersect. Currently, the lines ultimately get extended.
ex:
o1 = 0,0
p1 = 10,0
o2 = 5,5
p2 = 5,-5
Naturally, this would intersect at 5,0.
ex:
o1 = 0,0
p1 = 10,0
o2 = 5,5
p2 = 5,2
While the function also says this intersection is at 5,0, lines defined by the points however do not physically intersect, so in this case I'd want the function to return false.
I've considered modifying this function to at the end, check if r is between the two points for each line and came across the suggested formula of here.. I'm wondering if there might be a better or easier solution?

OpenCV 2d line intersection helper function

I was looking for a helper function to calculate the intersection of two lines in OpenCV. I have searched the API Documentation, but couldn't find a useful resource.
Are there basic geometric helper functions for intersection/distance calculations on lines/line segments in OpenCV?
There are no function in OpenCV API to calculate lines intersection, but distance is:
cv::Point2f start, end;
double length = cv::norm(end - start);
If you need a piece of code to calculate line intersections then here it is:
// Finds the intersection of two lines, or returns false.
// The lines are defined by (o1, p1) and (o2, p2).
bool intersection(Point2f o1, Point2f p1, Point2f o2, Point2f p2,
Point2f &r)
{
Point2f x = o2 - o1;
Point2f d1 = p1 - o1;
Point2f d2 = p2 - o2;
float cross = d1.x*d2.y - d1.y*d2.x;
if (abs(cross) < /*EPS*/1e-8)
return false;
double t1 = (x.x * d2.y - x.y * d2.x)/cross;
r = o1 + d1 * t1;
return true;
}
There's one cool trick in 2D geometry which I find to be very useful to calculate lines intersection. In order to use this trick we represent each 2D point and each 2D line in homogeneous 3D coordinates.
At first let's talk about 2D points:
Each 2D point (x, y) corresponds to a 3D line that passes through points (0, 0, 0) and (x, y, 1).
So (x, y, 1) and (α•x, α•y, α) and (β•x, β•y, β) correspond to the same point (x, y) in 2D space.
Here's formula to convert 2D point into homogeneous coordinates: (x, y) -> (x, y, 1)
Here's formula to convert homogeneous coordinates into 2D point: (x, y, ω) -> (x / ω, y / ω). If ω is zero that means "point at infinity". It doesn't correspond to any point in 2D space.
In OpenCV you may use convertPointsToHomogeneous() and convertPointsFromHomogeneous()
Now let's talk about 2D lines:
Each 2D line can be represented with three coordinates (a, b, c) which corresponds to 2D line equation: a•x + b•y + c = 0
So (a, b, c) and (ω•a, ω•b, ω•c) correspond to the same 2D line.
Also, (a, b, c) corresponds to (nx, ny, d) where (nx, ny) is unit length normal vector and d is distance from the line to (0, 0)
Also, (nx, ny, d) is (cos φ, sin φ, ρ) where (φ, ρ) are polar coordinates of the line.
There're two interesting formulas that link together points and lines:
Cross product of two distinct points in homogeneous coordinates gives homogeneous line coordinates: (α•x₁, α•y₁, α) ✕ (β•x₂, β•y₂, β) = (a, b, c)
Cross product of two distinct lines in homogeneous coordinates gives homogeneous coordinate of their intersection point: (a₁, b₁, c₁) ✕ (a₂, b₂, c₂) = (x, y, ω). If ω is zero that means lines are parallel (have no single intersection point in Euclidean geometry).
In OpenCV you may use either Mat::cross() or numpy.cross() to get cross product
If you're still here, you've got all you need to find lines given two points and intersection point given two lines.
An algorithm for finding line intersection is described very well in the post How do you detect where two line segments intersect?
The following is my openCV c++ implementation. It uses the same notation as in above post
bool getIntersectionPoint(Point a1, Point a2, Point b1, Point b2, Point & intPnt){
Point p = a1;
Point q = b1;
Point r(a2-a1);
Point s(b2-b1);
if(cross(r,s) == 0) {return false;}
double t = cross(q-p,s)/cross(r,s);
intPnt = p + t*r;
return true;
}
double cross(Point v1,Point v2){
return v1.x*v2.y - v1.y*v2.x;
}
Here is my implementation for EmguCV (C#).
static PointF GetIntersection(LineSegment2D line1, LineSegment2D line2)
{
double a1 = (line1.P1.Y - line1.P2.Y) / (double)(line1.P1.X - line1.P2.X);
double b1 = line1.P1.Y - a1 * line1.P1.X;
double a2 = (line2.P1.Y - line2.P2.Y) / (double)(line2.P1.X - line2.P2.X);
double b2 = line2.P1.Y - a2 * line2.P1.X;
if (Math.Abs(a1 - a2) < double.Epsilon)
throw new InvalidOperationException();
double x = (b2 - b1) / (a1 - a2);
double y = a1 * x + b1;
return new PointF((float)x, (float)y);
}
Using homogeneous coordinates makes your life easier:
cv::Mat intersectionPoint(const cv::Mat& line1, const cv::Mat& line2)
{
// Assume we receive lines as l=(a,b,c)^T
assert(line1.rows == 3 && line1.cols = 1
&& line2.rows == 3 && line2.cols == 1);
// Point is p=(x,y,w)^T
cv::Mat point = line1.cross(line2);
// Normalize so it is p'=(x',y',1)^T
if( point.at<double>(2,0) != 0)
point = point * (1.0/point.at<double>(2,0));
}
Note that if the third coordinate is 0 the lines are parallel and there is not solution in R² but in P^2, and then the point means a direction in 2D.
my implementation in Python (using numpy array)
with line1 = [[x1, y1],[x2, y2]] & line2 = [[x1, y1],[x2, y2]]
def getIntersection(line1, line2):
s1 = numpy.array(line1[0])
e1 = numpy.array(line1[1])
s2 = numpy.array(line2[0])
e2 = numpy.array(line2[1])
a1 = (s1[1] - e1[1]) / (s1[0] - e1[0])
b1 = s1[1] - (a1 * s1[0])
a2 = (s2[1] - e2[1]) / (s2[0] - e2[0])
b2 = s2[1] - (a2 * s2[0])
if abs(a1 - a2) < sys.float_info.epsilon:
return False
x = (b2 - b1) / (a1 - a2)
y = a1 * x + b1
return (x, y)

How could I make geometry advanced operations on bezier paths?

I have a library that draws regular bezier path figures (complex paths formed of a lot of bezier points), using midpoint approximation.
I can draw them without problem, but I need to add support for advanced geometry operations: Nearest point of a curve, intersection, figure contains point, and more importantly, path combinations: difference, intersection, exclusive-or, union, ...
Is there any good source to get all this?
Thanks
I've had to implement some of those operations on curves or closed paths. It mostly boils down to line and polygon operations. A few useful concepts:
The control points form a convex hull around the Bezier path, which is useful to short circuit intersection-related operations.
Your curve subdivision should be adaptive, stopping when the next subdivision won't be a significant difference, which means each "half" may divide to a different depth.
You can subdivide a curve at any point, not just the midpoint, which is useful for creating a Bezier subcurve ending at a found interestion point.
Example code for arbitrary subdivision:
static Point2D.Double[][] splitBezier(Point2D.Double[] p) {
return splitBezier(p, 0.5);
}
static Point2D.Double[][] splitBezier(Point2D.Double[] p, double t) {
Point2D.Double[][] parts = new Point2D.Double[2][4];
Point2D.Double ab = interpolate(t, p[0], p[1]);
Point2D.Double bc = interpolate(t, p[1], p[2]);
Point2D.Double cd = interpolate(t, p[2], p[3]);
Point2D.Double abc = interpolate(t, ab, bc);
Point2D.Double bcd = interpolate(t, bc, cd);
Point2D.Double abcd = interpolate(t, abc, bcd);
parts[0][0] = p[0];
parts[0][1] = ab;
parts[0][2] = abc;
parts[0][3] = abcd;
parts[1][0] = abcd;
parts[1][2] = bcd;
parts[1][2] = cd;
parts[1][3] = p[3];
return parts;
}
static Point2D.Double interpolate(double t, Point2D.Double a, Point2D.Double b) {
return new Point2D.Double((1 - t) * a.getX() + t * b.getX(),
(1 - t) * a.getY() + t * b.getY());
}
Some useful sites:
Details with applets
Discussion of more advanced intersection methods (PDF)

Resources