Boundary enclosing a given set of points - geometry

I am having a bit of a problem with an algorithm that I am currently using. I wanted it to make a boundary.
Here is an example of the current behavior:
Here is an MSPaint example of wanted behavior:
Current code of Convex Hull in C#:https://hastebin.com/dudejesuja.cs
So here are my questions:
1) Is this even possible?
R: Yes
2) Is this even called Convex Hull? (I don't think so)
R: Nope it is called boundary, link: https://www.mathworks.com/help/matlab/ref/boundary.html
3) Will this be less performance friendly than a conventional convex hull?
R: Well as far as I researched it should be the same performance
4) Example of this algorithm in pseudo code or something similar?
R: Not answered yet or I didn't find a solution yet

Here is some Python code that computes the alpha-shape (concave hull) and keeps only the outer boundary. This is probably what matlab's boundary does inside.
from scipy.spatial import Delaunay
import numpy as np
def alpha_shape(points, alpha, only_outer=True):
"""
Compute the alpha shape (concave hull) of a set of points.
:param points: np.array of shape (n,2) points.
:param alpha: alpha value.
:param only_outer: boolean value to specify if we keep only the outer border
or also inner edges.
:return: set of (i,j) pairs representing edges of the alpha-shape. (i,j) are
the indices in the points array.
"""
assert points.shape[0] > 3, "Need at least four points"
def add_edge(edges, i, j):
"""
Add an edge between the i-th and j-th points,
if not in the list already
"""
if (i, j) in edges or (j, i) in edges:
# already added
assert (j, i) in edges, "Can't go twice over same directed edge right?"
if only_outer:
# if both neighboring triangles are in shape, it's not a boundary edge
edges.remove((j, i))
return
edges.add((i, j))
tri = Delaunay(points)
edges = set()
# Loop over triangles:
# ia, ib, ic = indices of corner points of the triangle
for ia, ib, ic in tri.vertices:
pa = points[ia]
pb = points[ib]
pc = points[ic]
# Computing radius of triangle circumcircle
# www.mathalino.com/reviewer/derivation-of-formulas/derivation-of-formula-for-radius-of-circumcircle
a = np.sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
b = np.sqrt((pb[0] - pc[0]) ** 2 + (pb[1] - pc[1]) ** 2)
c = np.sqrt((pc[0] - pa[0]) ** 2 + (pc[1] - pa[1]) ** 2)
s = (a + b + c) / 2.0
area = np.sqrt(s * (s - a) * (s - b) * (s - c))
circum_r = a * b * c / (4.0 * area)
if circum_r < alpha:
add_edge(edges, ia, ib)
add_edge(edges, ib, ic)
add_edge(edges, ic, ia)
return edges
If you run it with the following test code you will get this figure, which looks like what you need:
from matplotlib.pyplot import *
# Constructing the input point data
np.random.seed(0)
x = 3.0 * np.random.rand(2000)
y = 2.0 * np.random.rand(2000) - 1.0
inside = ((x ** 2 + y ** 2 > 1.0) & ((x - 3) ** 2 + y ** 2 > 1.0)
points = np.vstack([x[inside], y[inside]]).T
# Computing the alpha shape
edges = alpha_shape(points, alpha=0.25, only_outer=True)
# Plotting the output
figure()
axis('equal')
plot(points[:, 0], points[:, 1], '.')
for i, j in edges:
plot(points[[i, j], 0], points[[i, j], 1])
show()
EDIT: Following a request in a comment, here is some code that "stitches" the output edge set into sequences of consecutive edges.
def find_edges_with(i, edge_set):
i_first = [j for (x,j) in edge_set if x==i]
i_second = [j for (j,x) in edge_set if x==i]
return i_first,i_second
def stitch_boundaries(edges):
edge_set = edges.copy()
boundary_lst = []
while len(edge_set) > 0:
boundary = []
edge0 = edge_set.pop()
boundary.append(edge0)
last_edge = edge0
while len(edge_set) > 0:
i,j = last_edge
j_first, j_second = find_edges_with(j, edge_set)
if j_first:
edge_set.remove((j, j_first[0]))
edge_with_j = (j, j_first[0])
boundary.append(edge_with_j)
last_edge = edge_with_j
elif j_second:
edge_set.remove((j_second[0], j))
edge_with_j = (j, j_second[0]) # flip edge rep
boundary.append(edge_with_j)
last_edge = edge_with_j
if edge0[0] == last_edge[1]:
break
boundary_lst.append(boundary)
return boundary_lst
You can then go over the list of boundary lists and append the points corresponding to the first index in each edge to get a boundary polygon.

I would use a different approach to solve this problem. Since we are working with a 2-D set of points, it is straightforward to compute the bounding rectangle of the points’ region. Then I would divide this rectangle into “cells” by horizontal and vertical lines, and for each cell simply count the number of pixels located within its bounds. Since each cell can have only 4 adjacent cells (adjacent by cell sides), then the boundary cells would be the ones that have at least one empty adjacent cell or have a cell side located at the bounding rectangle boundary. Then the boundary would be constructed along boundary cell sides. The boundary would look like a “staircase”, but choosing a smaller cell size would improve the result. As a matter of fact, the cell size should be determined experimentally; it could not be too small, otherwise inside the region may appear empty cells. An average distance between the points could be used as a lower boundary of the cell size.

Consider using an Alpha Shape, sometimes called a Concave Hull. https://en.wikipedia.org/wiki/Alpha_shape
It can be built from the Delaunay triangulation, in time O(N log N).

As pointed out by most previous experts, this might not be a convex hull but a concave hull, or an Alpha Shape in other words. Iddo provides a clean Python code to acquire this shape. However, you can also directly utilize some existing packages to realize that, perhaps with a faster speed and less computational memory if you are working with a large number of point clouds.
[1] Alpha Shape Toolbox: a toolbox for generating n-dimensional alpha shapes.
https://plotly.com/python/v3/alpha-shapes/
[2] Plotly: It can can generate a Mesh3d object, that depending on a key-value can be the convex hull of that set, its Delaunay triangulation, or an alpha set.
https://plotly.com/python/v3/alpha-shapes/

Here is the JavaScript code that builds concave hull: https://github.com/AndriiHeonia/hull Probably you can port it to C#.

One idea is creating triangles, a mesh, using the point cloud, perhaps through Delanuay triangulation,
and filling those triangles with a color then run level set, or active contour segmentation which will find the outer boundary of the shape whose color is now different then the outside "background" color.
https://xphilipp.developpez.com/contribuez/SnakeAnimation.gif
The animation above did not go all the way but many such algorithms can be configured to do that.
Note: The triangulation alg has to be tuned so that it doesn't merely create a convex hull - for example removing triangles with too large angles and sides from the delanuay result. A prelim code could look like
from scipy.spatial import Delaunay
points = np.array([[13.43, 12.89], [14.44, 13.86], [13.67, 15.87], [13.39, 14.95],\
[12.66, 13.86], [10.93, 14.24], [11.69, 15.16], [13.06, 16.24], [11.29, 16.35],\
[10.28, 17.33], [10.12, 15.49], [9.03, 13.76], [10.12, 14.08], [9.07, 15.87], \
[9.6, 16.68], [7.18, 16.19], [7.62, 14.95], [8.39, 16.79], [8.59, 14.51], \
[8.1, 13.43], [6.57, 11.59], [7.66, 11.97], [6.94, 13.86], [6.53, 14.84], \
[5.48, 12.84], [6.57, 12.56], [5.6, 11.27], [6.29, 10.08], [7.46, 10.45], \
[7.78, 7.21], [7.34, 8.72], [6.53, 8.29], [5.85, 8.83], [5.56, 10.24], [5.32, 7.8], \
[5.08, 9.86], [6.01, 5.75], [6.41, 7.48], [8.19, 5.69], [8.23, 4.72], [6.85, 6.34], \
[7.02, 4.07], [9.4, 3.2], [9.31, 4.99], [7.86, 3.15], [10.73, 2.82], [10.32, 4.88], \
[9.72, 1.58], [11.85, 5.15], [12.46, 3.47], [12.18, 1.58], [11.49, 3.69], \
[13.1, 4.99], [13.63, 2.61]])
tri = Delaunay(points,furthest_site=False)
res = []
for t in tri.simplices:
A,B,C = points[t[0]],points[t[1]],points[t[2]]
e1 = B-A; e2 = C-A
num = np.dot(e1, e2)
n1 = np.linalg.norm(e1); n2 = np.linalg.norm(e2)
denom = n1 * n2
d1 = np.rad2deg(np.arccos(num/denom))
e1 = C-B; e2 = A-B
num = np.dot(e1, e2)
denom = np.linalg.norm(e1) * np.linalg.norm(e2)
d2 = np.rad2deg(np.arccos(num/denom))
d3 = 180-d1-d2
res.append([n1,n2,d1,d2,d3])
res = np.array(res)
m = res[:,[0,1]].mean()*res[:,[0,1]].std()
mask = np.any(res[:,[2,3,4]] > 110) & (res[:,0] < m) & (res[:,1] < m )
plt.triplot(points[:,0], points[:,1], tri.simplices[mask])
Then fill with color and segment.

Related

extract mean of circle patche in python

i have some X/Y coordinates that represent the center of a circle somewhere in an image. From that circle, i want to compoute the mean of all the point contained inside the circle.
currently, i compute the mean of a square patche as follow, but a square is not relevent for the project. Ideally, i would like to do it only with numpy. but if it is not possible, i would concidere something else.
mean = np.mean(image[Y - margin : Y + margin, X - margin, X + margin])
As I understood,
YOU HAVE: (x,y) of the center of the circle
YOU WANT: mean of all the points contained in the circle
Since all the points on the right side should be equal to the number of points on the left side of the center, Wouldn't the mean be the same as the center of the circle !?
i found a solution where I compute all indexes contained in a centered disk.
I calculate the squarred euclidean distance of each X/Y coordinate of a squarre array.
I compare it to the squarred radius of the circle.
If it is superior, the point is not contained in the circle. Mark it as 0, 1 otherwise
I extract indexes where the array is equal to one (disk-shaped)
I center the computed indexes. To use them, i add the X/Y coordinate of a specific image point.
NOTE: I used the squarred euclidean distance because the square root function is monotonic (i.e constantly increasing). So, it saves compational power to keep with the squarred version.
radius = 4
size = 2 * radius + 1
radiusSquarred= radius**2
mask = np.zeros((size, size))
distance = lambda x, y: (x-radius)**2 + (y-radius)**2
for i in range(size):
for j in range (2 * radius+ 1):
if distance(i, j) <= radiusSquarred:
mask[i, j] = 1
index = np.where(mask == 1)
diskIndexes = (index[0] - radius, index[1] - radius)
X, Y = 100, 150
np.mean(image[diskIndexes[0] + Y, diskIndexes[1] + X])

How to find coordinates (as Natural numbers) of two points that form a tangent line for a circle limited by the x axis?

Two points P and Q with coordinates (Px, Py) and (Qx, Qy) satisfy the following properties:
The coordinates Px, Py, Qx, and Qy are integers.
Px = −Qx.
The line PQ is tangent to a circle with center (0, 0) and radius r
0 < Px ≤ a for some integer limit a.
How do I find all such pairs of points P and Q?
For example, in the image below I have a circle with radius r=2 and the limit a = 6. The pair of points P = (6, 2) and Q = (−6, −7) are a solution, because:
The coordinates of P and Q are integers.
Px = −Qx.
The line PQ is tangent to the circle.
0 < Px ≤ 6.
But this is just one pair. I need to find all such pairs. There are a finite number of solutions.
So, is there a way to check if coordinates of points are tangent to the circle and are integers, then to list them all? I've looked at slope equations and shortest path from the center of the circle to the line equations, however, in the first case it requires coordinates to be known (which I could do by brute forcing every single digit, but I cannot see the pattern, because my guts tell me there should be some sort of equation I should apply), and in the second case I have to know the slope equation.
This is the algorithm I came up with but I don't think it is correct or good enough:
Find the slope equation y = mx + b for all 1 ≤ Px ≤ a and −a ≤ Qx ≤ −1.
For every y = mx + b check if it is tangent to the circle (how to do that???)
If true, return the pair
Line PQ has equation:
(x-Px)/(Qx-Px)=(y-Py)/(Qy-Py) or
(x-Px)*(Qy-Py)-(y-Py)*(Qx-Px)=0 or
x*(Qy-Py)+y*(Px-Qx)-Px*Qy+Px*Py+Py*Qx-Py*Px =
x*(Qy-Py)+y*2*Px-Px*(Qy+Py)=0
Distance from zero point to this line (circle radius) is
r=Px*(Qy+Py)/Sqrt((2*Px)^2+(Qy-Py)^2)
Note that radius and nominator are integers, so denominator must be integer too. It is possible when 2*Px and |Qy-Py| are members of some Pythagorean triple (for your example - 12^2+9^2 =15^2).So you can use "Generating a triple" method from the above link to significantly reduce the search and find all the possible point pairs (with radius checking)
Px = k * m * n (for m>=n, radius < k*m*n <= a)
|Qy-Py| = k * (m^2 - n^2)
With a=6 max value of n is 2, and your example corresponds to (k, m, n) set of (3, 2, 1)

Best fit square to quadrilateral

I've got a shape consisting of four points, A, B, C and D, of which the only their position is known. The goal is to transform these points to have specific angles and offsets relative to each other.
For example: A(-1,-1) B(2,-1) C(1,1) D(-2,1), which should be transformed to a perfect square (all angles 90) with offsets between AB, BC, CD and AD all being 2. The result should be a square slightly rotated counter-clockwise.
What would be the most efficient way to do this?
I'm using this for a simple block simulation program.
As Mark alluded, we can use constrained optimization to find the side 2 square that minimizes the square of the distance to the corners of the original.
We need to minimize f = (a-A)^2 + (b-B)^2 + (c-C)^2 + (d-D)^2 (where the square is actually a dot product of the vector argument with itself) subject to some constraints.
Following the method of Lagrange multipliers, I chose the following distance constraints:
g1 = (a-b)^2 - 4
g2 = (c-b)^2 - 4
g3 = (d-c)^2 - 4
and the following angle constraints:
g4 = (b-a).(c-b)
g5 = (c-b).(d-c)
A quick napkin sketch should convince you that these constraints are sufficient.
We then want to minimize f subject to the g's all being zero.
The Lagrange function is:
L = f + Sum(i = 1 to 5, li gi)
where the lis are the Lagrange multipliers.
The gradient is non-linear, so we have to take a hessian and use multivariate Newton's method to iterate to a solution.
Here's the solution I got (red) for the data given (black):
This took 5 iterations, after which the L2 norm of the step was 6.5106e-9.
While Codie CodeMonkey's solution is a perfectly valid one (and a great use case for the Lagrangian Multipliers at that), I believe that it's worth mentioning that if the side length is not given this particular problem actually has a closed form solution.
We would like to minimise the distance between the corners of our fitted square and the ones of the given quadrilateral. This is equivalent to minimising the cost function:
f(x1,...,y4) = (x1-ax)^2+(y1-ay)^2 + (x2-bx)^2+(y2-by)^2 +
(x3-cx)^2+(y3-cy)^2 + (x4-dx)^2+(y4-dy)^2
Where Pi = (xi,yi) are the corners of the fitted square and A = (ax,ay) through D = (dx,dy) represent the given corners of the quadrilateral in clockwise order. Since we are fitting a square we have certain contraints regarding the positions of the four corners. Actually, if two opposite corners are given, they are enough to describe a unique square (save for the mirror image on the diagonal).
Parametrization of the points
This means that two opposite corners are enough to represent our target square. We can parametrise the two remaining corners using the components of the first two. In the above example we express P2 and P4 in terms of P1 = (x1,y1) and P3 = (x3,y3). If you need a visualisation of the geometrical intuition behind the parametrisation of a square you can play with the interactive version.
P2 = (x2,y2) = ( (x1+x3-y3+y1)/2 , (y1+y3-x1+x3)/2 )
P4 = (x4,y4) = ( (x1+x3+y3-y1)/2 , (y1+y3+x1-x3)/2 )
Substituting for x2,x4,y2,y4 means that f(x1,...,y4) can be rewritten to:
f(x1,x3,y1,y3) = (x1-ax)^2+(y1-ay)^2 + ((x1+x3-y3+y1)/2-bx)^2+((y1+y3-x1+x3)/2-by)^2 +
(x3-cx)^2+(y3-cy)^2 + ((x1+x3+y3-y1)/2-dx)^2+((y1+y3+x1-x3)/2-dy)^2
a function which only depends on x1,x3,y1,y3. To find the minimum of the resulting function we then set the partial derivatives of f(x1,x3,y1,y3) equal to zero. They are the following:
df/dx1 = 4x1-dy-dx+by-bx-2ax = 0 --> x1 = ( dy+dx-by+bx+2ax)/4
df/dx3 = 4x3+dy-dx-by-bx-2cx = 0 --> x3 = (-dy+dx+by+bx+2cx)/4
df/dy1 = 4y1-dy+dx-by-bx-2ay = 0 --> y1 = ( dy-dx+by+bx+2ay)/4
df/dy3 = 4y3-dy-dx-2cy-by+bx = 0 --> y3 = ( dy+dx+by-bx+2cy)/4
You may see where this is going, as simple rearrangment of the terms leads to the final solution.
Final solution

Define a function for a circle caps the end of a line segment

I need a function that returns points on a circle in three dimensions.
The circle should "cap" a line segment defined by points A and B and it's radius. each cap is perpendicular to the line segment. and centered at one of the endpoints.
Here is a shitty diagram
Let N be the unit vector in the direction from A to B, i.e., N = (B-A) / length(A-B). The first step is to find two more vectors X and Y such that {N, X, Y} form a basis. That means you want two more vectors so that all pairs of {N, X, Y} are perpendicular to each other and also so that they are all unit vectors. Another way to think about this is that you want to create a new coordinate system whose x-axis lines up with the line segment. You need to find vectors pointing in the direction of the y-axis and z-axis.
Note that there are infinitely many choices for X and Y. You just need to somehow find two that work.
One way to do this is to first find vectors {N, W, V} where N is from above and W and V are two of (1,0,0), (0,1,0), and (0,0,1). Pick the two vectors for W and V that correspond to the smallest coordinates of N. So if N = (.31, .95, 0) then you pick (1,0,0) and (0,0,1) for W and V. (Math geek note: This way of picking W and V ensures that {N,W,V} spans R^3). Then you apply the Gram-Schmidt process to {N, W, V} to get vectors {N, X, Y} as above. Note that you need the vector N to be the first vector so that it doesn't get changed by the process.
So now you have two vectors that are perpendicular to the line segment and perpendicular to each other. This means the points on the circle around A are X * cos t + Y * sin t + A where 0 <= t < 2 * pi. This is exactly like the usual description of a circle in two dimensions; it is just written in the new coordinate system described above.
As David Norman noted the crux is to find two orthogonal unit vectors X,Y that are orthogonal to N. However I think a simpler way to compute these is by finding the householder reflection Q that maps N to a multiple of (1,0,0) and then to take as X the image of (0,1,0) under Q and Y as the image of (0,0,1) under Q. While this might sound complicated it comes down to:
s = (N[0] > 0.0) ? 1.0 : -1.0
t = N[0] + s; f = -1.0/(s*t);
X[0] = f*N[1]*t; X[1] = 1 + f*N[1]*N[1]; X[2] = f*N[1]*N[2];
Y[0] = f*N[2]*t; Y[1] = f*N[1]*N[2]; Y[2] = 1 + f*N[2]*N[2];

Projective transformation

Given two image buffers (assume it's an array of ints of size width * height, with each element a color value), how can I map an area defined by a quadrilateral from one image buffer into the other (always square) image buffer? I'm led to understand this is called "projective transformation".
I'm also looking for a general (not language- or library-specific) way of doing this, such that it could be reasonably applied in any language without relying on "magic function X that does all the work for me".
An example: I've written a short program in Java using the Processing library (processing.org) that captures video from a camera. During an initial "calibrating" step, the captured video is output directly into a window. The user then clicks on four points to define an area of the video that will be transformed, then mapped into the square window during subsequent operation of the program. If the user were to click on the four points defining the corners of a door visible at an angle in the camera's output, then this transformation would cause the subsequent video to map the transformed image of the door to the entire area of the window, albeit somewhat distorted.
Using linear algebra is much easier than all that geometry! Plus you won't need to use sine, cosine, etc, so you can store each number as a rational fraction and get the exact numerical result if you need it.
What you want is a mapping from your old (x,y) co-ordinates to your new (x',y') co-ordinates. You can do it with matrices. You need to find the 2-by-4 projection matrix P such that P times the old coordinates equals the new co-ordinates. We'll assume that you're mapping lines to lines (not, for instance, straight lines to parabolas). Because you have a projection (parallel lines don't stay parallel) and translation (sliding), you need a factor of (xy) and (1), too. Drawn as matrices:
[x ]
[a b c d]*[y ] = [x']
[e f g h] [x*y] [y']
[1 ]
You need to know a through h so solve these equations:
a*x_0 + b*y_0 + c*x_0*y_0 + d = i_0
a*x_1 + b*y_1 + c*x_1*y_1 + d = i_1
a*x_2 + b*y_2 + c*x_2*y_2 + d = i_2
a*x_3 + b*y_3 + c*x_3*y_3 + d = i_3
e*x_0 + f*y_0 + g*x_0*y_0 + h = j_0
e*x_1 + f*y_1 + g*x_1*y_1 + h = j_1
e*x_2 + f*y_2 + g*x_2*y_2 + h = j_2
e*x_3 + f*y_3 + g*x_3*y_3 + h = j_3
Again, you can use linear algebra:
[x_0 y_0 x_0*y_0 1] [a e] [i_0 j_0]
[x_1 y_1 x_1*y_1 1] * [b f] = [i_1 j_1]
[x_2 y_2 x_2*y_2 1] [c g] [i_2 j_2]
[x_3 y_3 x_3*y_3 1] [d h] [i_3 j_3]
Plug in your corners for x_n,y_n,i_n,j_n. (Corners work best because they are far apart to decrease the error if you're picking the points from, say, user-clicks.) Take the inverse of the 4x4 matrix and multiply it by the right side of the equation. The transpose of that matrix is P. You should be able to find functions to compute a matrix inverse and multiply online.
Where you'll probably have bugs:
When computing, remember to check for division by zero. That's a sign that your matrix is not invertible. That might happen if you try to map one (x,y) co-ordinate to two different points.
If you write your own matrix math, remember that matrices are usually specified row,column (vertical,horizontal) and screen graphics are x,y (horizontal,vertical). You're bound to get something wrong the first time.
EDIT
The assumption below of the invariance of angle ratios is incorrect. Projective transformations instead preserve cross-ratios and incidence. A solution then is:
Find the point C' at the intersection of the lines defined by the segments AD and CP.
Find the point B' at the intersection of the lines defined by the segments AD and BP.
Determine the cross-ratio of B'DAC', i.e. r = (BA' * DC') / (DA * B'C').
Construct the projected line F'HEG'. The cross-ratio of these points is equal to r, i.e. r = (F'E * HG') / (HE * F'G').
F'F and G'G will intersect at the projected point Q so equating the cross-ratios and knowing the length of the side of the square you can determine the position of Q with some arithmetic gymnastics.
Hmmmm....I'll take a stab at this one. This solution relies on the assumption that ratios of angles are preserved in the transformation. See the image for guidance (sorry for the poor image quality...it's REALLY late). The algorithm only provides the mapping of a point in the quadrilateral to a point in the square. You would still need to implement dealing with multiple quad points being mapped to the same square point.
Let ABCD be a quadrilateral where A is the top-left vertex, B is the top-right vertex, C is the bottom-right vertex and D is the bottom-left vertex. The pair (xA, yA) represent the x and y coordinates of the vertex A. We are mapping points in this quadrilateral to the square EFGH whose side has length equal to m.
Compute the lengths AD, CD, AC, BD and BC:
AD = sqrt((xA-xD)^2 + (yA-yD)^2)
CD = sqrt((xC-xD)^2 + (yC-yD)^2)
AC = sqrt((xA-xC)^2 + (yA-yC)^2)
BD = sqrt((xB-xD)^2 + (yB-yD)^2)
BC = sqrt((xB-xC)^2 + (yB-yC)^2)
Let thetaD be the angle at the vertex D and thetaC be the angle at the vertex C. Compute these angles using the cosine law:
thetaD = arccos((AD^2 + CD^2 - AC^2) / (2*AD*CD))
thetaC = arccos((BC^2 + CD^2 - BD^2) / (2*BC*CD))
We map each point P in the quadrilateral to a point Q in the square. For each point P in the quadrilateral, do the following:
Find the distance DP:
DP = sqrt((xP-xD)^2 + (yP-yD)^2)
Find the distance CP:
CP = sqrt((xP-xC)^2 + (yP-yC)^2)
Find the angle thetaP1 between CD and DP:
thetaP1 = arccos((DP^2 + CD^2 - CP^2) / (2*DP*CD))
Find the angle thetaP2 between CD and CP:
thetaP2 = arccos((CP^2 + CD^2 - DP^2) / (2*CP*CD))
The ratio of thetaP1 to thetaD should be the ratio of thetaQ1 to 90. Therefore, calculate thetaQ1:
thetaQ1 = thetaP1 * 90 / thetaD
Similarly, calculate thetaQ2:
thetaQ2 = thetaP2 * 90 / thetaC
Find the distance HQ:
HQ = m * sin(thetaQ2) / sin(180-thetaQ1-thetaQ2)
Finally, the x and y position of Q relative to the bottom-left corner of EFGH is:
x = HQ * cos(thetaQ1)
y = HQ * sin(thetaQ1)
You would have to keep track of how many colour values get mapped to each point in the square so that you can calculate an average colour for each of those points.
I think what you're after is a planar homography, have a look at these lecture notes:
http://www.cs.utoronto.ca/~strider/vis-notes/tutHomography04.pdf
If you scroll down to the end you'll see an example of just what you're describing. I expect there's a function in the Intel OpenCV library which will do just this.
There is a C++ project on CodeProject that includes source for projective transformations of bitmaps. The maths are on Wikipedia here. Note that so far as i know, a projective transformation will not map any arbitrary quadrilateral onto another, but will do so for triangles, you may also want to look up skewing transforms.
If this transformation has to look good (as opposed to the way a bitmap looks if you resize it in Paint), you can't just create a formula that maps destination pixels to source pixels. Values in the destination buffer have to be based on a complex averaging of nearby source pixels or else the results will be highly pixelated.
So unless you want to get into some complex coding, use someone else's magic function, as smacl and Ian have suggested.
Here's how would do it in principle:
map the origin of A to the origin of B via a traslation vector t.
take unit vectors of A (1,0) and (0,1) and calculate how they would be mapped onto the unit vectors of B.
this gives you a transformation matrix M so that every vector a in A maps to M a + t
invert the matrix and negate the traslation vector so for every vector b in B you have the inverse mapping b -> M-1 (b - t)
once you have this transformation, for each point in the target area in B, find the corresponding in A and copy.
The advantage of this mapping is that you only calculate the points you need, i.e. you loop on the target points, not the source points. It was a widely used technique in the "demo coding" scene a few years back.

Resources