Bit Shifting with units of measure in F# - f#

I have three types of position - called Position, WalkPosition and TilePosition. I've converted them to units of measure, and it is much cleaner, but some things just don't quite work for me.
Unfortunately, I'm not using purely F# (there's a C++ interface exposed via CLI - fun times!). Firstly, for converting in and out, I've used * 1<tile> and * 1<1/tile> because I noticed a performance hit on my use of int. That's all well and good until I start trying to do interesting things with generics. I'm currently stumped by the getApproxDistance function, with an operator I'm calling |~|. This version assumes no unit of measure attached to my Position:
[<Measure>] type pixel
[<Measure>] type walk
[<Measure>] type tile
module Position =
type Position<[<Measure>] 'u> = Pos of int<'u> * int<'u> with
static member inline (+) (Pos (x1, y1), Pos (x2, y2)) = Pos (x1 + x2, y1 + y2)
static member inline (-) (Pos (x1, y1), Pos (x2, y2)) = Pos (x1 - x2, y1 - y2)
static member inline (*) (Pos (x, y), f) = Pos (x * f, y * f)
static member inline (/) (Pos (x, y), d) = Pos (x / d, y / d)
// getApproxDistance as per Starcraft: Broodwar
static member (|~|) (Pos (x1, y1), Pos (x2, y2)) =
let xDist = abs (x1 - x2)
let yDist = abs (y1 - y2)
let largeDist, smallDist = max xDist yDist, min xDist yDist
if smallDist < (largeDist >>> 2) then largeDist
else
let smallCalc = (3*smallDist) >>> 3
((smallCalc >>> 5) + smallCalc + largeDist - (largeDist >>> 4) - (largeDist >>> 6))
// Precise length calc - may be slow
static member inline (|-|) (Pos (x1, y1), Pos (x2, y2)) =
pown (x1 - x2) 2 + pown (y1 - y2) 2 |> float |> sqrt
let inline posx (Pos (_x, _)) = _x
let inline posy (Pos (_, _y)) = _y
let PixelPerWalk : int<pixel/walk> = 8<pixel/walk>
let PixelPerTile : int<pixel/tile> = 32<pixel/tile>
let WalkPerTile : int<walk/tile> = 4<walk/tile>
let inline walkToPixel (pos:Position<_>) = pos * PixelPerWalk
let inline tileToPixel (pos:Position<_>) = pos * PixelPerTile
let inline pixelToWalk (pos:Position<_>) = pos / PixelPerWalk
let inline tileToWalk (pos:Position<_>) = pos * WalkPerTile
let inline pixelToTile (pos:Position<_>) = pos / PixelPerTile
let inline walkToTile (pos:Position<_>) = pos / WalkPerTile
let example = Pos (1<walk>, 2<walk>) |~| Pos (2<walk>, 1<walk>)
I'd be content to rip the unit of measure off (|> int doesn't seem to slow it down in this scenario) and add it back on the returned distance, but it seems I can't do that. I can't even overload an inline call, because you can't overload purely on units of measure. Ideas?

The error that you are seeing is because the units of measure in your |~| function are being constrained to 1. This means that an int<walk> is not a valid input to this function.
You are correct that the int function will strip units of measure from something of type int<'u>. What you may not be aware of is that you can use LanguagePrimitives.Int32WithMeasure<'u> to add a particular unit of measure.
You can therefore write |~|:
static member (|~|) (Pos (x1 : int<'u>, y1 : int<'u>), Pos (x2 : int<'u>, y2 : int<'u>)) =
let xDist = abs (int x1 - int x2)
let yDist = abs (int y1 - int y2)
let largeDist, smallDist = max xDist yDist, min xDist yDist
if smallDist < (largeDist >>> 2) then
largeDist
|> LanguagePrimitives.Int32WithMeasure<'u>
else
let smallCalc = (3*smallDist) >>> 3
((smallCalc >>> 5) + smallCalc + largeDist - (largeDist >>> 4) - (largeDist >>> 6))
|> LanguagePrimitives.Int32WithMeasure<'u>
Your example:
let example = Pos (1<walk>, 2<walk>) |~| Pos (2<walk>, 1<walk>)
This then has the correct type: int<walk>.
You shouldn't need to worry about the performance impact of stripping away/adding units of measure, they are just a compile time construct - unit of measure information is not retained at runtime.
By the way, you also don't really need all of those inline keywords everywhere, you aren't doing anything with statically resolved type parameters, see https://msdn.microsoft.com/en-us/library/dd548047.aspx for more detail about use of inline.

Related

How to convert bounding box (x1, y1, x2, y2) to YOLO Style (X, Y, W, H)

I'm training a YOLO model, I have the bounding boxes in this format:-
x1, y1, x2, y2 => ex (100, 100, 200, 200)
I need to convert it to YOLO format to be something like:-
X, Y, W, H => 0.436262 0.474010 0.383663 0.178218
I already calculated the center point X, Y, the height H, and the weight W.
But still need a away to convert them to floating numbers as mentioned.
for those looking for the reverse of the question (yolo format to normal bbox format)
def yolobbox2bbox(x,y,w,h):
x1, y1 = x-w/2, y-h/2
x2, y2 = x+w/2, y+h/2
return x1, y1, x2, y2
Here's code snipet in python to convert x,y coordinates to yolo format
def convert(size, box):
dw = 1./size[0]
dh = 1./size[1]
x = (box[0] + box[1])/2.0
y = (box[2] + box[3])/2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
im=Image.open(img_path)
w= int(im.size[0])
h= int(im.size[1])
print(xmin, xmax, ymin, ymax) #define your x,y coordinates
b = (xmin, xmax, ymin, ymax)
bb = convert((w,h), b)
Check my sample program to convert from LabelMe annotation tool format to Yolo format https://github.com/ivder/LabelMeYoloConverter
There is a more straight-forward way to do those stuff with pybboxes. Install with,
pip install pybboxes
use it as below,
import pybboxes as pbx
voc_bbox = (100, 100, 200, 200)
W, H = 1000, 1000 # WxH of the image
pbx.convert_bbox(voc_bbox, from_type="voc", to_type="yolo", image_size=(W,H))
>>> (0.15, 0.15, 0.1, 0.1)
Note that, converting to YOLO format requires the image width and height for scaling.
YOLO normalises the image space to run from 0 to 1 in both x and y directions. To convert between your (x, y) coordinates and yolo (u, v) coordinates you need to transform your data as u = x / XMAX and y = y / YMAX where XMAX, YMAX are the maximum coordinates for the image array you are using.
This all depends on the image arrays being oriented the same way.
Here is a C function to perform the conversion
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <math.h>
struct yolo {
float u;
float v;
};
struct yolo
convert (unsigned int x, unsigned int y, unsigned int XMAX, unsigned int YMAX)
{
struct yolo point;
if (XMAX && YMAX && (x <= XMAX) && (y <= YMAX))
{
point.u = (float)x / (float)XMAX;
point.v = (float)y / (float)YMAX;
}
else
{
point.u = INFINITY;
point.v = INFINITY;
errno = ERANGE;
}
return point;
}/* convert */
int main()
{
struct yolo P;
P = convert (99, 201, 255, 324);
printf ("Yolo coordinate = <%f, %f>\n", P.u, P.v);
exit (EXIT_SUCCESS);
}/* main */
There are two potential solutions. First of all you have to understand if your first bounding box is in the format of Coco or Pascal_VOC. Otherwise you can't do the right math.
Here is the formatting;
Coco Format: [x_min, y_min, width, height]
Pascal_VOC Format: [x_min, y_min, x_max, y_max]
Here are some Python Code how you can do the conversion:
Converting Coco to Yolo
# Convert Coco bb to Yolo
def coco_to_yolo(x1, y1, w, h, image_w, image_h):
return [((2*x1 + w)/(2*image_w)) , ((2*y1 + h)/(2*image_h)), w/image_w, h/image_h]
Converting Pascal_voc to Yolo
# Convert Pascal_Voc bb to Yolo
def pascal_voc_to_yolo(x1, y1, x2, y2, image_w, image_h):
return [((x2 + x1)/(2*image_w)), ((y2 + y1)/(2*image_h)), (x2 - x1)/image_w, (y2 - y1)/image_h]
If need additional conversions you can check my article at Medium: https://christianbernecker.medium.com/convert-bounding-boxes-from-coco-to-pascal-voc-to-yolo-and-back-660dc6178742
For yolo format to x1,y1, x2,y2 format
def yolobbox2bbox(x,y,w,h):
x1 = int((x - w / 2) * dw)
x2 = int((x + w / 2) * dw)
y1 = int((y - h / 2) * dh)
y2 = int((y + h / 2) * dh)
if x1 < 0:
x1 = 0
if x2 > dw - 1:
x2 = dw - 1
if y1 < 0:
y1 = 0
if y2 > dh - 1:
y2 = dh - 1
return x1, y1, x2, y2
There are two things you need to do:
Divide the coordinates by the image size to normalize them to [0..1] range.
Convert (x1, y1, x2, y2) coordinates to (center_x, center_y, width, height).
If you're using PyTorch, Torchvision provides a function that you can use for the conversion:
from torch import tensor
from torchvision.ops import box_convert
image_size = tensor([608, 608])
boxes = tensor([[100, 100, 200, 200], [300, 300, 400, 400]], dtype=float)
boxes[:, :2] /= image_size
boxes[:, 2:] /= image_size
boxes = box_convert(boxes, "xyxy", "cxcywh")
Just reading the answers I am also looking for this but find this more informative to know what happening at the backend.
Form Here: Source
Assuming x/ymin and x/ymax are your bounding corners, top left and bottom right respectively. Then:
x = xmin
y = ymin
w = xmax - xmin
h = ymax - ymin
You then need to normalize these, which means give them as a proportion of the whole image, so simple divide each value by its respective size from the values above:
x = xmin / width
y = ymin / height
w = (xmax - xmin) / width
h = (ymax - ymin) / height
This assumes a top-left origin, you will have to apply a shift factor if this is not the case.
So the answer

F# arrays to 2D histogram

I’m using OxyPlot with F#. I have code to create a single parameter histogram and plot it. My code for dual parameter histograms in the form of a contour is too time consuming. I’d like an efficient way to map two vectors or arrays into a 2D histogram. I’m including my code for regular histogram.
let myHistogram c =
flatten dataArray.[c..c,*]
|> Seq.toArray
|> Array.map (fun x -> round(float(x)/16.0))
|> Seq.countBy (fun x -> x)
|> Seq.sort
|> Seq.map snd
So, I’m looking to take dataArray.[a…a,], dataArray[b…b,] and place them into bins of a specific resolution to create histogram[x,y]. OxyPlot needs the histogram in order to create a contour.
Imagine two arrays of data with one being called Alexa647-H and the other BV786-H. Each array contains 100,000 integers ranging between 0 and 10,000. You could plot these arrays as a dot plot in OxyPlot. That is straight forward, simply plot one array for the X-Axis and one array for the Y-Axis. I've included a plot below.
My question involves creating a contour plot out of the same data. For that, I need to first determine a resolution, say for convenience 100x100. Therefore I want to end up with a 2D array call hist2(100,100). The array is basically 10,000 bins of 1000x1000 in size. Each bin contains the count of elements which fall into a particular range -- a 2D histogram.
Dot and Contour
The coding example in OxyPlot generates a peak array mathematically. I want to generate that contour input peak array as outline above, instead.
var model = new PlotModel { Title = "ContourSeries" };
double x0 = -3.1;
double x1 = 3.1;
double y0 = -3;
double y1 = 3;
//generate values
Func<double, double, double> peaks = (x, y) => 3 * (1 - x) * (1 - x) * Math.Exp(-(x * x) - (y + 1) * (y + 1)) - 10 * (x / 5 - x * x * x - y * y * y * y * y) * Math.Exp(-x * x - y * y) - 1.0 / 3 * Math.Exp(-(x + 1) * (x + 1) - y * y);
var xx = ArrayBuilder.CreateVector(x0, x1, 100);
var yy = ArrayBuilder.CreateVector(y0, y1, 100);
var peaksData = ArrayBuilder.Evaluate(peaks, xx, yy);
var cs = new ContourSeries
{
Color = OxyColors.Black,
LabelBackground = OxyColors.White,
ColumnCoordinates = yy,
RowCoordinates = xx,
Data = peaksData
};
model.Series.Add(cs);
Plot generated by OxyPlot code
I hope this clears things up.
Don

Torch / Lua, how to pair together to arrays into a table?

I need to use the Pearson correlation coefficient in my Torch / Lua program.
This is the function:
function math.pearson(a)
-- compute the mean
local x1, y1 = 0, 0
for _, v in pairs(a) do
x1, y1 = x1 + v[1], y1 + v[2]
print('x1 '..x1);
print('y1 '..y1);
end
-- compute the coefficient
x1, y1 = x1 / #a, y1 / #a
local x2, y2, xy = 0, 0, 0
for _, v in pairs(a) do
local tx, ty = v[1] - x1, v[2] - y1
xy, x2, y2 = xy + tx * ty, x2 + tx * tx, y2 + ty * ty
end
return xy / math.sqrt(x2) / math.sqrt(y2)
end
This function wants an input couple table that can be used in the pairs() function.
I tried to submit to it the right input table but I was not able to get anything working.
I tried with:
z = {}
a = {27, 29, 45, 98, 1293, 0.1}
b = {0.0001, 0.001, 0.32132, 0.0001, 0.0009}
z = {a,b}
But unfortunately it does not work. It will compute pairs between the first elements of b, while I want it to compute the correlation between a and b.
How could I do?
Can you provide a good object that may work as input to the math.pearson() function?
If you are using this implementation, then I think it expects a different parameter structure. You should be passing a table of two-value tables, as in:
local z = {
{27, 0.0001}, {29, 0.001}, {45, 0.32132}, {98, 0.0001}, {1293, 0.0009}
}
print(math.pearson(z))
This prints -0.25304101592759 for me.

FORTRAN counter loop returns multiple iterations of the same value

First of all I am a complete novice to FORTRAN. With that said I am attempting to "build" a box, then randomly generate x, y, z coordinates for 100 atoms. From there, the goal is to calculate the distance between each atom, which becomes the value "r" of the Lennard-Jones potential energy equation. Then calculate the LJ potential, and finally sum the potential of the entire box. A previous question that I had asked about this project is here. The problem is that I get the same calculated value over and over and over again. My code is below.
program energytot
implicit none
integer, parameter :: n = 100
integer :: i, j, k, seed(12)
double precision :: sigma, r, epsilon, lx, ly, lz
double precision, dimension(n) :: x, y, z, cx, cy, cz
double precision, dimension(n*(n+1)/2) :: dx, dy, dz, LJx, LJy, LJz
sigma = 4.1
epsilon = 1.7
!Box length with respect to the axis
lx = 15
ly = 15
lz = 15
do i=1,12
seed(i)=i+3
end do
!generate n random numbers for x, y, z
call RANDOM_SEED(PUT = seed)
call random_number(x)
call random_number(y)
call random_number(z)
!convert random numbers into x, y, z coordinates
cx = ((2*x)-1)*(lx*0.5)
cy = ((2*y)-1)*(lx*0.5)
cz = ((2*z)-1)*(lz*0.5)
do j=1,n-1
do k=j+1,n
dx = ABS((cx(j) - cx(k)))
LJx = 4 * epsilon * ((sigma/dx(j))**12 - (sigma/dx(j))**6)
dy = ABS((cy(j) - cy(k)))
LJy = 4 * epsilon * ((sigma/dy(j))**12 - (sigma/dy(j))**6)
dz = ABS((cz(j) - cz(k)))
LJz = 4 * epsilon * ((sigma/dz(j))**12 - (sigma/dz(j))**6)
end do
end do
print*, dx
end program energytot
What exactly is your question? What do you want your code to do, and what does it do instead?
If you're having problems with the final print statement print*, dx, try this instead:
print *, 'dx = '
do i = 1, n * (n + 1) / 2
print *, dx(i)
end do
It seems that dx is too big to be printed without a loop.
Also, it looks like you're repeatedly assigning the array dx (and other arrays in the loop) to a single value. Try this instead:
i = 0
do j=1,n-1
do k=j+1,n
i = i + 1
dx(i) = ABS((cx(j) - cx(k)))
end do
end do
This way, each value cx(j) - cx(k) gets saved to a different element of dx, instead of overwriting previously saved values.
My new code goes something like this:
program energytot
implicit none
integer, parameter :: n = 6
integer :: i, j, k, seed(12)
double precision :: sigma, r, epsilon, lx, ly, lz, etot, pot, rx, ry, rz
double precision, dimension(n) :: x, y, z, cx, cy, cz
sigma = 4.1
epsilon = 1.7
etot=0
!Box length with respect to the axis
lx = 15
ly = 15
lz = 15
do i=1,12
seed(i)=i+90
end do
!generate n random numbers for x, y, z
call RANDOM_SEED(PUT = seed)
call random_number(x)
call random_number(y)
call random_number(z)
!convert random numbers into x, y, z coordinates
cx = ((2*x)-1)*(lx*0.5)
cy = ((2*y)-1)*(lx*0.5)
cz = ((2*z)-1)*(lz*0.5)
do j=1,n-1
do k=j+1,n
rx = (cx(j) - cx(k))
ry = (cy(j) - cy(k))
rz = (cz(j) - cz(k))
!Apply minimum image convention
rx=rx-lx*anint(rx/lx)
ry=ry-ly*anint(ry/ly)
rz=rz-lz*anint(rz/lz)
r=sqrt(rx**2+ry**2+rz**2)
pot=4 * epsilon * ((sigma/r)**12 - (sigma/r)**6)
print*,pot
etot=etot+pot
end do
end do
print*, etot
end program energytot

finding the distance between one camera and one object, knowing the dimensions of the object using opencv

I am working on robotic arm, and trying to find the distance between one camera and one object, knowing the dimensions of the object using open CV.
I not sure how to do it.
I tried using visual servoing method but not succeeded.
Any help will be nice
Here is a simple solution for starting:
1.) First, you have to calibrate your camera to receive the C matrix. For example:
http://docs.opencv.org/doc/tutorials/calib3d/camera_calibration/camera_calibration.html
2.) Then you have to identify on the image two points of the object which distance is known. Let's be these points P1(X1, Y1, Z1) and P2(X2, Y2, Z2) in the 3D space and p1(x1, y1) and p2(x2, y2) in 2D image plane. Certainly P1 and P2 are not known, only their pairs on the image (p1 and p2) and their distance D.
3.) Next, if you know the camera calibration matrix C, you have two equations:
p1 = C * P1 and p2 = C * P2
Then: C^-1 * p1 = P1' and C^-1 * p2 = P2' where P1' = (X1 / Z1, Y1 / Z1, 1) and P2' = (X2 / Z2, Y2 / Z2, 1). This means that C^-1 * p1 returns the 3D coordinates of the point belong the Z1 = 1 distance.
But the exact distance is not 1 but it is Z1 and Z2. Now, let's suppose that Z1 == Z2 == Z and we are looking for the distance Z.
This follows that Z * C^-1 * p1 = P1 and Z * C^-1 * p2 = P2.
Next (Z * C^-1 * p1) - (Z * C^-1 * p2) = P1 - P2, and
Z * ((C^-1 * p1) - C^-1 * p2)) = P1 - P2, and
Z^2 * ((C^-1 * p1) - C^-1 * p2))^2 = (P1 - P2)^2 = D^2
Now, C, p1, p2 and D are known, only Z is the unknown variable in the last equation.
Certainly, this is only a basic solution and uses the assumpion that the distances of the object's points are very similar, but it can work.

Resources