Running cv::warpPerspective on points - visual-c++

I'm running the cv::warpPerspective() function on a image and what to get the position of the some points of result image the I get in the source image, here how far I came :
int main (){
cv::Point2f srcQuad[4],dstQuad[4];
cv::Mat warpMatrix;
cv::Mat src, dst,src2;
src = cv::imread("card.jpg",1);
srcQuad[0].x = 0; //src Top left
srcQuad[0].y = 0;
srcQuad[1].x = src.cols - 1; //src Top right
srcQuad[1].y = 0;
srcQuad[2].x = 0; //src Bottom left
srcQuad[2].y = src.rows - 1;
srcQuad[3].x = src.cols -1; //src Bot right
srcQuad[3].y = src.rows - 1;
dstQuad[0].x = src.cols*0.05; //dst Top left
dstQuad[0].y = src.rows*0.33;
dstQuad[1].x = src.cols*0.9; //dst Top right
dstQuad[1].y = src.rows*0.25;
dstQuad[2].x = src.cols*0.2; //dst Bottom left
dstQuad[2].y = src.rows*0.7;
dstQuad[3].x = src.cols*0.8; //dst Bot right
dstQuad[3].y = src.rows*0.9;
warpMatrix =cv::getPerspectiveTransform(srcQuad,dstQuad);
cv::warpPerspective(src,dst,warpMatrix,src.size());
cv::imshow("source", src);
cv::imshow("destination", dst);
cv::warpPerspective(dst,src2,warpMatrix,dst.size(),CV_WARP_INVERSE_MAP);
cv::imshow("srouce 2 " , src2);
cv::waitKey();
return 0;
my problem is that if I select a point from dst how can get its coordinates in ** src or src2 ** since the cv::warpPerspective function doesn't take cv::Point as parameter ??

You want perspectiveTransform (which works on a vector of Points) rather than warpPerspective.
Take the inverse of warpMatrix; you may have to tweak the final column.
vector<Point2f> dstPoints, srcPoints;
dstPoints.push_back(Point2f(1,1));
cv::perspectiveTransform(dstPoints,srcPoints,warpMatrix.inv());

A perspective transform relates two points in the following manner:
[x'] [m00 m01 m02] [x]
[y'] = [m10 m11 m12] [y]
[1] [m20 m21 m22] [1]
Where (x,y) are the original 2D point coordinates, and (x', y') are the transformed coordinates.
In your case, you know (x', y'), and want to know (x, y). This can be achieved by multiplying the known point by the inverse of the transformation matrix:
cv::Matx33f warp = warpMatrix; // cv::Matx is much more useful for math
cv::Point2f warped_point = dstQuad[3]; // I just use dstQuad as an example
cv::Point3f homogeneous = warp.inv() * warped_point;
cv::Point2f result(homogeneous.x, homogeneous.y); // Drop the z=1 to get out of homogeneous coordinates
// now, result == srcQuad[3], which is what you wanted

Related

Can Jarvis marching algorith return UNso0rted results?

I am trying to compute a complex hull for a very complex point set. See picture:
The green/teal line to the left contains convex hull points that are neighboring, i.e. come directly after one another. continuing the sequence, the next point should be the cyan/green one in right bottom.
However, if i walk along the array, the next one appears to be the one in top right, in yellow.
Yes, output is in ascii, point cloud is correct (compared with GUI output) .
Snippet:
for(int i = 0; i< rd.length; i++) {
if( (*rd)[i].lon < lonMin) {
lonMin = (*rd)[i].lon;
leftMostPos = i;
}
}
int [] hullIdx = new int[0];
int p = leftMostPos, m = to!int((*rd).length), q;
do {
hullIdx ~= [p];
q = (p + 1) % m;
for ( int ij = 0; ij < m ; ij ++) {
auto a = (*rd)[p];
auto b = (*rd)[ij];
auto c = (*rd)[q];
double ornt = (b.lat - a.lat) * ( c.lon - b.lon) - (b.lon - a.lon) * (c.lat - b.lat) ;
if (ornt < 0) q = ij;
}
p = q;
} while ( p != leftMostPos);
Language is D, I am solving for Geographical Lats and Lons. Lons are taken as a coordinates, lats are in x coordinate. The Matrix increases y coordinate by row, towards downward direction. This is also taken into account.
I would like to know how come Jarvis algorithm returns UNsorted output. I would apppreciate all your help with gratefulness.

Color interpolation with a set of 2D points

I am trying to modelize a physical problem of photoelasticity on a surface. I succeed to get an array of X,Y - coordinates of the surface and for each points I have a corresponding color in a RGB format. I used Python scatter to plot and the result is already great but there is still some discontinuities because of the lack of resolution that I can not improve :( I just wanted to ask how I can generate the same surface plot in a continuous way (with new "in-between" points for which the color of them have been interpolated with respect to the neighborhood points). I am not necessarily looking for coding it in python, every software is welcome. Thanks!
I wrote this in javascript: https://jsfiddle.net/87nw05kz/
The important part is calculateColor. It finds the inverse square of the distance to each color from the pixel being shaded and it uses that to decide how much that pixel should be effected by each color.
function calculateColor(x, y) {
let total = 0;
for (let i = 0; i < colors.length; i++) {
let c = colors[i];
let d = distance(c.x, c.y, x, y);
if (d === 0) {
return c;
}
d = 1 / (d * d);
c.d = d;
total += d;
}
let r = 0, g = 0, b = 0;
for (let i = 0; i < colors.length; i++) {
let c = colors[i];
let ratio = c.d / total;
r += ratio * c.r;
g += ratio * c.g;
b += ratio * c.b;
}
r = Math.floor(r);
g = Math.floor(g);
b = Math.floor(b);
return {r:r,g:g,b:b};
}

Simulate virtual camera which preserves color information

I have a virtual scanner that generates a 2.5-D view of a point cloud (i.e. a 2D-projection of a 3D point cloud) depending on camera position. I'm using the vtkCamera.GetProjectionTransformMatrix() to get transformation matrix from world/global to camera coordinates.
However, if the input point cloud has color information for points I would like to preserve it.
Here are the relevant lines:
boost::shared_ptr<pcl::visualization::PCLVisualizer> vis; // camera location, viewpoint and up direction for vis were already defined before
vtkSmartPointer<vtkRendererCollection> rens = vis->getRendererCollection();
vtkSmartPointer<vtkRenderWindow> win = vis->getRenderWindow();
win->SetSize(xres, yres); // xres and yres are predefined resolutions
win->Render();
float dwidth = 2.0f / float(xres),
dheight = 2.0f / float(yres);
float *depth = new float[xres * yres];
win->GetZbufferData(0, 0, xres - 1, yres - 1, &(depth[0]));
vtkRenderer *ren = rens->GetFirstRenderer();
vtkCamera *camera = ren->GetActiveCamera();
vtkSmartPointer<vtkMatrix4x4> projection_transform = camera->GetProjectionTransformMatrix(ren->GetTiledAspectRatio(), 0, 1);
Eigen::Matrix4f mat1;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
mat1(i, j) = static_cast<float> (projection_transform->Element[i][j]);
mat1 = mat1.inverse().eval();
Now, mat1 is used to transform coordinates to camera-view:
pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud;
int ptr = 0;
for (int y = 0; y < yres; ++y)
{
for (int x = 0; x < xres; ++x, ++ptr)
{
pcl::PointXYZ &pt = (*cloud)[ptr];
if (depth[ptr] == 1.0)
{
pt.x = pt.y = pt.z = std::numeric_limits<float>::quiet_NaN();
continue;
}
Eigen::Vector4f world_coords(dwidth * float(x) - 1.0f,
dheight * float(y) - 1.0f,
depth[ptr],
1.0f);
world_coords = mat1 * world_coords;
float w3 = 1.0f / world_coords[3];
world_coords[0] *= w3;
world_coords[1] *= w3;
world_coords[2] *= w3;
pt.x = static_cast<float> (world_coords[0]);
pt.y = static_cast<float> (world_coords[1]);
pt.z = static_cast<float> (world_coords[2]);
}
}
I want the virtual scanner to return pcl::PointXYZRGB point cloud with color information.
Any help on how to implement this from someone experienced in VTK would save some of my time.
It's possible that I missed a relevant question already asked here - in that case, please point me to it. Thanks.
If I understand correctly that you want to get the color in which the point was rendered into the win RenderWindow, you should be able to get the data from the rendering buffer by calling
float* pixels = win->GetRGBAPixelData(0, 0, xres - 1, yres - 1, 0/1).
This should give you each pixel of the rendering buffer as an array in the format [R0, G0, B0, A0, R1, G1, B1, A1, R2....]. The last parameter which I wrote as 0/1 is whether the data should be taken from front or back opengl buffers. I presume by default double buffering should be on, so then you want to read from back buffer (use '1'), but I am not sure.
Once you have that, you can get the color in your second loop for all pixels that belong to points (depth[ptr] != 1.0) as:
pt.R = pixels[4*ptr];
pt.G = pixels[4*ptr + 1];
pt.B = pixels[4*ptr + 2];
You should call win->ReleaseRGBAPixelData(pixels) once you're done with it.

Fill a closed path in easeljs

Is there a way to fill a closed drawn path in easeljs? I have along string of mt(x_t,y_t).lt(x_(t+1),y_(t+1)) that draws a wacky shape. the shape closes off, but I can't find a way to have it actually fill in the closed area. Any ideas?
T is how many coordinates there are to connect, [round.X, round.Y] is the Tx2 array of coordinate pairs, ghf is the graphics object. xline.y is just a the lowest y value.
for(var i=0;i<T;i++){
x0 = round.X[i];
y0 = round.Y[i];
// scale for drawing
px0 = Math.round(xscale * x0);
py0 = Math.round(yscale * y0) + xline.y;
if(x0>gp.xmin){ // if not first point ...
ghf.mt(prevx,prevy).lt(px0,py0); // draw line from prev point to this point
}
// set this point as prev point
prevx = px0;
prevy = py0;
}
// fill out thing
ghf.mt(prevx,prevy).lt(px0,xline.y);
ghf.mt(px0,xline.y).lt(0,xline.y);
x0 = round.X[0];
y0 = round.Y[0];
px0 = Math.round(xscale * x0);
py0 = Math.round(yscale * y0) + xline.y;
ghf.mt(0,xline.y).lt(px0,py0);
ghf.f('red');
Your code is not very helpful, but I think what you need is the beginFill method. See link.
You can use it like this:
var ball = new createjs.Shape();
ball.graphics.setStrokeStyle(5, 'round', 'round');
ball.graphics.beginStroke(('#000000'));
ball.graphics.beginFill("#FF0000").drawCircle(0,0,50);
ball.graphics.endStroke();
ball.graphics.endFill();
ball.graphics.setStrokeStyle(1, 'round', 'round');
ball.graphics.beginStroke(('#000000'));
ball.graphics.moveTo(0,0);
ball.graphics.lineTo(0,50);

DirectX 11: text output, using your own font texture

I'm learning DirectX, using the book "Sherrod A., Jones W. - Beginning DirectX 11 Game Programming - 2011" Now I'm exploring the 4th chapter about drawing text.
Please, help we to fix my function, that I'm using to draw a string on the screen. I've already loaded font texture and in the function I create some sprites with letters and define texture coordinates for them. This compiles correctly, but doesn't draw anything. What's wrong?
bool DirectXSpriteGame :: DrawString(char* StringToDraw, float StartX, float StartY)
{
//VAR
HRESULT D3DResult; //The result of D3D functions
int i; //Counters
const int IndexA = static_cast<char>('A'); //ASCII index of letter A
const int IndexZ = static_cast<char>('Z'); //ASCII index of letter Z
int StringLenth = strlen(StringToDraw); //Lenth of drawing string
float ScreenCharWidth = static_cast<float>(LETTER_WIDTH) / static_cast<float>(SCREEN_WIDTH); //Width of the single char on the screen(in %)
float ScreenCharHeight = static_cast<float>(LETTER_HEIGHT) / static_cast<float>(SCREEN_HEIGHT); //Height of the single char on the screen(in %)
float TexelCharWidth = 1.0f / static_cast<float>(LETTERS_NUM); //Width of the char texel(in the texture %)
float ThisStartX; //The start x of the current letter, drawingh
float ThisStartY; //The start y of the current letter, drawingh
float ThisEndX; //The end x of the current letter, drawing
float ThisEndY; //The end y of the current letter, drawing
int LetterNum; //Letter number in the loaded font
int ThisLetter; //The current letter
D3D11_MAPPED_SUBRESOURCE MapResource; //Map resource
VertexPos* ThisSprite; //Vertecies of the current sprite, drawing
//VAR
//Clamping string, if too long
if(StringLenth > LETTERS_NUM)
{
StringLenth = LETTERS_NUM;
}
//Mapping resource
D3DResult = _DeviceContext -> Map(_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MapResource);
if(FAILED(D3DResult))
{
throw("Failed to map resource");
}
ThisSprite = (VertexPos*)MapResource.pData;
for(i = 0; i < StringLenth; i++)
{
//Creating geometry for the letter sprite
ThisStartX = StartX + ScreenCharWidth * static_cast<float>(i);
ThisStartY = StartY;
ThisEndX = ThisStartX + ScreenCharWidth;
ThisEndY = StartY + ScreenCharHeight;
ThisSprite[0].Position = XMFLOAT3(ThisEndX, ThisEndY, 1.0f);
ThisSprite[1].Position = XMFLOAT3(ThisEndX, ThisStartY, 1.0f);
ThisSprite[2].Position = XMFLOAT3(ThisStartX, ThisStartY, 1.0f);
ThisSprite[3].Position = XMFLOAT3(ThisStartX, ThisStartY, 1.0f);
ThisSprite[4].Position = XMFLOAT3(ThisStartX, ThisEndY, 1.0f);
ThisSprite[5].Position = XMFLOAT3(ThisEndX, ThisEndY, 1.0f);
ThisLetter = static_cast<char>(StringToDraw[i]);
//Defining the letter place(number) in the font
if(ThisLetter < IndexA || ThisLetter > IndexZ)
{
//Invalid character, the last character in the font, loaded
LetterNum = IndexZ - IndexA + 1;
}
else
{
LetterNum = ThisLetter - IndexA;
}
//Unwraping texture on the geometry
ThisStartX = TexelCharWidth * static_cast<float>(LetterNum);
ThisStartY = 0.0f;
ThisEndY = 1.0f;
ThisEndX = ThisStartX + TexelCharWidth;
ThisSprite[0].TextureCoords = XMFLOAT2(ThisEndX, ThisEndY);
ThisSprite[1].TextureCoords = XMFLOAT2(ThisEndX, ThisStartY);
ThisSprite[2].TextureCoords = XMFLOAT2(ThisStartX, ThisStartY);
ThisSprite[3].TextureCoords = XMFLOAT2(ThisStartX, ThisStartY);
ThisSprite[4].TextureCoords = XMFLOAT2(ThisStartX, ThisEndY);
ThisSprite[5].TextureCoords = XMFLOAT2(ThisEndX, ThisEndY);
ThisSprite += VERTEX_IN_RECT_NUM;
}
for(i = 0; i < StringLenth; i++, ThisSprite -= VERTEX_IN_RECT_NUM);
_DeviceContext -> Unmap(_vertexBuffer, 0);
_DeviceContext -> Draw(VERTEX_IN_RECT_NUM * StringLenth, 0);
return true;
}
Although the piece of code constructing the Vertex Array seems correct to me at first glance, it seems like you are trying to Draw your vertices with a Shader which has not been set yet !
It is difficult to precisely answer you without looking at the whole code, but I can guess that you will need to do something like that :
1) Create Vertex and Pixel Shaders by compiling them first from their respective buffers
2) Create the Input Layout description, which describes the Input Buffers that will be read by the Input Assembler stage. It will have to match your VertexPos structure and your shader structure.
3) Set the Shader parameters.
4) Only now you can Set Shader rendering parameters : Set the InputLayout, as well as the Vertex and Pixel Shaders that will be used to render your triangles by something like :
_DeviceContext -> Unmap(_vertexBuffer, 0);
_DeviceContext->IASetInputLayout(myInputLayout);
_DeviceContext->VSSetShader(myVertexShader, NULL, 0); // Set Vertex shader
_DeviceContext->PSSetShader(myPixelShader, NULL, 0); // Set Pixel shader
_DeviceContext -> Draw(VERTEX_IN_RECT_NUM * StringLenth, 0);
This link should help you achieve what you want to do : http://www.rastertek.com/dx11tut12.html
Also, I recommend you to set an IndexBuffer and to use the method DrawIndexed to render your triangles for performance reasons : It will allow the graphics adapter to store vertices in a vertex cache, allowing recently-used vertex to be fetched from the cache instead of reading it from the vertex buffer.
More about this concern can be found on MSDN : http://msdn.microsoft.com/en-us/library/windows/desktop/bb147325(v=vs.85).aspx
Hope this helps!
P.S : Also, don't forget to release the resources after using them by calling Release().

Resources