Zoom and pan two images simultaneously in opencv - opencv

I have two images with similar sizes that show similar scenes. How can we show two images in two frames and when panning or zooming in the left image, it pans and zooms in the right one? I don't want to concatenate the images though.
Is there a solution to do this? Both python or c++ OpenCV are fine.

About zoom in/out:
The basic idea is deciding the scale changed every time on mouse wheel. After you get the current scale (v.s. origin image) and correct region of image you want to show on screen, you can get the position and length of rectangle on scaled image. So you can draw this rectangle on scaled image.
In my github,checking OnMouseWheel () and RefreshSrcView () in Fastest_Image_Pattern_Matching/ELCVMatchTool/ELCVMatchToolDlg.cpp may give what you want.
About showing two images simutaneouly with same region:
use two picture boxes with MFC framework or other UI builder.
or use two cv::namedWindow () without framework
Effect:
Part of the code:
BOOL CELCVMatchToolDlg::OnMouseWheel (UINT nFlags, short zDelta, CPoint pt)
{
POINT pointCursor;
GetCursorPos (&pointCursor);
ScreenToClient (&pointCursor);
// TODO: 在此加入您的訊息處理常式程式碼和 (或) 呼叫預設值
if (zDelta > 0)
{
if (m_iScaleTimes == MAX_SCALE_TIMES)
return TRUE;
else
m_iScaleTimes++;
}
if (zDelta < 0)
{
if (m_iScaleTimes == MIN_SCALE_TIMES)
return TRUE;
else
m_iScaleTimes--;
}
CRect rect;
//GetWindowRect (rect);
GetDlgItem (IDC_STATIC_SRC_VIEW)->GetWindowRect (rect);//重要
if (m_iScaleTimes == 0)
g_dCompensationX = g_dCompensationY = 0;
int iMouseOffsetX = pt.x - (rect.left + 1);
int iMouseOffsetY = pt.y - (rect.top + 1);
double dPixelX = (m_hScrollBar.GetScrollPos () + iMouseOffsetX + g_dCompensationX) / m_dNewScale;
double dPixelY = (m_vScrollBar.GetScrollPos () + iMouseOffsetY + g_dCompensationY) / m_dNewScale;
m_dNewScale = m_dSrcScale * pow (SCALE_RATIO, m_iScaleTimes);
if (m_iScaleTimes != 0)
{
int iWidth = m_matSrc.cols;
int iHeight = m_matSrc.rows;
m_hScrollBar.SetScrollRange (0, int (m_dNewScale * iWidth - m_dSrcScale * iWidth) - 1 + BAR_SIZE);
m_vScrollBar.SetScrollRange (0, int (m_dNewScale * iHeight - m_dSrcScale * iHeight) - 1 + BAR_SIZE);
int iBarPosX = int (dPixelX * m_dNewScale - iMouseOffsetX + 0.5);
m_hScrollBar.SetScrollPos (iBarPosX);
m_hScrollBar.ShowWindow (SW_SHOW);
g_dCompensationX = -iBarPosX + (dPixelX * m_dNewScale - iMouseOffsetX);
int iBarPosY = int (dPixelY * m_dNewScale - iMouseOffsetY + 0.5);
m_vScrollBar.SetScrollPos (iBarPosY);
m_vScrollBar.ShowWindow (SW_SHOW);
g_dCompensationY = -iBarPosY + (dPixelY * m_dNewScale - iMouseOffsetY);
//滑塊大小
SCROLLINFO infoH;
infoH.cbSize = sizeof (SCROLLINFO);
infoH.fMask = SIF_PAGE;
infoH.nPage = BAR_SIZE;
m_hScrollBar.SetScrollInfo (&infoH);
SCROLLINFO infoV;
infoV.cbSize = sizeof (SCROLLINFO);
infoV.fMask = SIF_PAGE;
infoV.nPage = BAR_SIZE;
m_vScrollBar.SetScrollInfo (&infoV);
//滑塊大小
}
else
{
m_hScrollBar.SetScrollPos (0);
m_hScrollBar.ShowWindow (SW_HIDE);
m_vScrollBar.SetScrollPos (0);
m_vScrollBar.ShowWindow (SW_HIDE);
}
RefreshSrcView ();
return CDialogEx::OnMouseWheel (nFlags, zDelta, pt);
}

Related

Working out heightmap normals in DirectX using triangle strips

I'm trying to load in heightmap data but I'm struggling to figure out how to work out the normals. Have looked online but can't seem to find anything useful.
I store the vertices using
m_HeightMapVtxCount = (m_HeightMapLength - 1) * m_HeightMapWidth * 2;
m_pVertices = new XMFLOAT3[m_HeightMapVtxCount];
Then the vertices are loaded in using
for (int l = 0; l < m_HeightMapLength - 1; ++l)
{
if(l % 2 == 0) //for every second row - start at the bottom left corner, continue to the right, one row up and continue to the left
{
for(int w = 0; w < m_HeightMapWidth; ++w)
{
m_pVertices[i++] = XMFLOAT3(m_pHeightMap[w + l * m_HeightMapWidth]); //bottom vertex
m_pVertices[i++] = XMFLOAT3(m_pHeightMap[w + (l + 1) * m_HeightMapWidth]); //top vertex
}
}
else //for the row above, add the vertices from right to left
{
for(int w = m_HeightMapWidth - 1; w >= 0; --w)
{
m_pVertices[i++] = XMFLOAT3(m_pHeightMap[w + l * m_HeightMapWidth]); //bottom vertex
m_pVertices[i++] = XMFLOAT3(m_pHeightMap[w + (l + 1) * m_HeightMapWidth]); //top vertex
}
}
}
I was able to calculate the normals using triangle lists, that was quite simple, but unsure of how to do it using strips

Triangle Gradient With Core Graphics

I'm trying to draw a triangle like this one in a view (one UIView, one NSView):
My first thought was CoreGraphics, but I couldn't find any information that would help me draw a gradient between three points of arbitrary color.
Any help?
Thanks!
Actually it's pretty simple with CoreGraphics. Below you can find code that renders given triangle, but first let's think how we can solve this problem.
Theory
Imagine equilateral triangle with side length w. All three angles are equal to 60 degrees:
Each angle will represent component of a pixel: red, green or blue.
Lets analyze intensity of a green component in a pixel near top angle:
The more closer pixel to the angle, the more component intense it'll have and vice versa. Here we can decompose our main goal to smaller ones:
Draw triangle pixel by pixel.
For each pixel calculate value for each component based on distance from corresponding angle.
To solve first task we will use CoreGraphics bitmap context. It will have four components per pixel each 8 bits long. This means that component value may vary from 0 to 255. Fourth component is alpha channel and will be always equal to max value - 255. Here is example of how values will be interpolated for the top angle:
Now we need to think how we can calculate value for component.
First, let's define main color for each angle:
Now let's choose an arbitrary point A with coordinates (x,y) on the triangle:
Next, we draw a line from an angle associated with red component and it passes through the A till it intersects with opposite side of a triangle:
If we could find d and c their quotient will equal to normalized value of component, so value can be calculated easily:
(source: sciweavers.org)
Formula for finding distance between two points is simple:
(source: sciweavers.org)
We can easily find distance for d, but not for c, because we don't have coordinates of intersection. Actually it's not that hard. We just need to build line equations for line that passes through A and line that describes opposite side of a triangle and find their intersection:
Having intersection point we can apply distance formula to find c and finally calculate component value for current point.
Same flow applies for another components.
Code
Here is the code that implements concepts above:
+ (UIImage *)triangleWithSideLength:(CGFloat)sideLength {
return [self triangleWithSideLength:sideLength scale:[UIScreen mainScreen].scale];
}
+ (UIImage *)triangleWithSideLength:(CGFloat)sideLength
scale:(CGFloat)scale {
UIImage *image = nil;
CGSize size = CGSizeApplyAffineTransform((CGSize){sideLength, sideLength * sin(M_PI / 3)}, CGAffineTransformMakeScale(scale, scale));
size_t const numberOfComponents = 4;
size_t width = ceilf(size.width);
size_t height = ceilf(size.height);
size_t realBytesPerRow = width * numberOfComponents;
size_t alignedBytesPerRow = (realBytesPerRow + 0xFF) & ~0xFF;
size_t alignedPixelsPerRow = alignedBytesPerRow / numberOfComponents;
CGContextRef ctx = CGBitmapContextCreate(NULL,
width,
height,
8,
alignedBytesPerRow,
CGColorSpaceCreateDeviceRGB(),
(CGBitmapInfo)kCGImageAlphaPremultipliedLast);
char *data = CGBitmapContextGetData(ctx);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int edge = ceilf((height - i) / sqrt(3));
if (j < edge || j > width - edge) {
continue;
}
CGFloat redNormalized = 0;
CGFloat greenNormalized = 0;
CGFloat blueNormalized = 0;
CGPoint currentTrianglePoint = (CGPoint){j / scale, (height - i) / scale};
[self calculateCurrentValuesAtGiventPoint:currentTrianglePoint
sideLength:sideLength
sideOne:&redNormalized
sideTwo:&greenNormalized
sideThree:&blueNormalized];
int32_t red = redNormalized * 0xFF;
int32_t green = greenNormalized * 0xFF;
int32_t blue = blueNormalized * 0xFF;
char *pixel = data + (j + i * alignedPixelsPerRow) * numberOfComponents;
*pixel = red;
*(pixel + 1) = green;
*(pixel + 2) = blue;
*(pixel + 3) = 0xFF;
}
}
CGImageRef cgImage = CGBitmapContextCreateImage(ctx);
image = [[UIImage alloc] initWithCGImage:cgImage];
CGContextRelease(ctx);
CGImageRelease(cgImage);
return image;
}
+ (void)calculateCurrentValuesAtGiventPoint:(CGPoint)point
sideLength:(CGFloat)length
sideOne:(out CGFloat *)sideOne
sideTwo:(out CGFloat *)sideTwo
sideThree:(out CGFloat *)sideThree {
CGFloat height = sin(M_PI / 3) * length;
if (sideOne != NULL) {
// Side one is at 0, 0
CGFloat currentDistance = sqrt(point.x * point.x + point.y * point.y);
if (currentDistance != 0) {
CGFloat a = point.y / point.x;
CGFloat b = 0;
CGFloat c = -height / (length / 2);
CGFloat d = 2 * height;
CGPoint intersection = (CGPoint){(d - b) / (a - c), (a * d - c * b) / (a - c)};
CGFloat currentH = sqrt(intersection.x * intersection.x + intersection.y * intersection.y);
*sideOne = 1 - currentDistance / currentH;
} else {
*sideOne = 1;
}
}
if (sideTwo != NULL) {
// Side two is at w, 0
CGFloat currentDistance = sqrt(pow((point.x - length), 2) + point.y * point.y);
if (currentDistance != 0) {
CGFloat a = point.y / (point.x - length);
CGFloat b = height / (length / 2);
CGFloat c = a * -point.x + point.y;
CGFloat d = b * -length / 2 + height;
CGPoint intersection = (CGPoint){(d - c) / (a - b), (a * d - b * c) / (a - b)};
CGFloat currentH = sqrt(pow(length - intersection.x, 2) + intersection.y * intersection.y);
*sideTwo = 1 - currentDistance / currentH;
} else {
*sideTwo = 1;
}
}
if (sideThree != NULL) {
// Side three is at w / 2, w * sin60 degrees
CGFloat currentDistance = sqrt(pow((point.x - length / 2), 2) + pow(point.y - height, 2));
if (currentDistance != 0) {
float dy = point.y - height;
float dx = (point.x - length / 2);
if (fabs(dx) > FLT_EPSILON) {
CGFloat a = dy / dx;
CGFloat b = 0;
CGFloat c = a * -point.x + point.y;
CGFloat d = 0;
CGPoint intersection = (CGPoint){(d - c) / (a - b), (a * d - b * c) / (a - b)};
CGFloat currentH = sqrt(pow(length / 2 - intersection.x, 2) + pow(height - intersection.y, 2));
*sideThree = 1 - currentDistance / currentH;
} else {
*sideThree = 1 - currentDistance / height;
}
} else {
*sideThree = 1;
}
}
}
Here is a triangle image produced by this code:

CGRectIntersectsRect for multiple CGRect

I have 8 UIImageView, which have to be placed randomly. I generate a random x,y pos for each imageView, then I need to check if any of the imageViews are intersecting. If they are intersecting, it goes back to calculating random x,y pos again(do..while loop). Now the only method I know of is CGRectIntersectsRect, which can only compare 2 CGRect. Is there a way I can check if all those imageViews intersect at once (inside the while condition)?
Here's what I already worked out for 3 images-
do {
xpos1 = 60 + arc4random() % (960 - 60 + 1);
ypos1 = 147 + arc4random() % (577 - 147 + 1);
xpos2 = 60 + arc4random() % (960 - 60 + 1);
ypos2 = 147 + arc4random() % (577 - 147 + 1);
xpos3 = 60 + arc4random() % (960 - 60 + 1);
ypos3 = 147 + arc4random() % (577 - 147 + 1);
} while (CGRectIntersectsRect(CGRectMake(xpos1, ypos1,120, 120), CGRectMake(xpos2, ypos2,120, 120)) || CGRectIntersectsRect(CGRectMake(xpos2, ypos2,120,120), CGRectMake(xpos3, ypos3, 120, 120)) || CGRectIntersectsRect(CGRectMake(xpos1, ypos1,120,120), CGRectMake(xpos3, ypos3, 120, 120)) );
image1.center=CGPointMake(xpos1, ypos1);
image2.center=CGPointMake(xpos2, ypos2);
image3.center=CGPointMake(xpos3, ypos3);
A simple algorithm would be to start with one rectangle, and then iteratively find new rectangles
that do not intersect with any of the previous ones:
int numRects = 8;
CGFloat xmin = 60, xmax = 960, ymin = 147, ymax = 577;
CGFloat width = 120, height = 120;
CGRect rects[numRects];
for (int i = 0; i < numRects; i++) {
bool intersects;
do {
// Create random rect:
CGFloat x = xmin + arc4random_uniform(xmax - xmin + 1);
CGFloat y = ymin + arc4random_uniform(ymax - ymin + 1);
rects[i] = CGRectMake(x, y, width, height);
// Check if it intersects with one of the previous rects:
intersects = false;
for (int j = 0; j < i; j++) {
if (CGRectIntersectsRect(rects[i], rects[j])) {
intersects = true;
break;
}
}
// repeat until new rect does not intersect with previous rects:
} while (intersects);
}
This should answer your question ("how to check for intersection with multiple rectangles"),
but note that this method is not perfect. If the rectangles would fill "much" of the
available space and the first rectangles are placed "badly" then the algorithm might not
terminate because it cannot find an admissible rectangle at some point.
I don't think that can happen with the dimensions used in your case, but you might keep that
in mind. A possible solution could be to count the number of tries that were made, and if
it takes too long than start over from the beginning.
Also, if you have to create many rectangles then the inner loop (that checks for the
intersection) can be improved by sorting the rectangles, so that less comparisons have to
be made.
Say you have generated point
CGFloat x = (CGFloat) (arc4random() % (int) self.view.bounds.size.width);
CGFloat y = (CGFloat) (arc4random() % (int) self.view.bounds.size.height);
CGPoint point=CGPointMake(x, y);
while ([self checkPointExist:point]) {
x = (CGFloat) (arc4random() % (int) self.view.bounds.size.width);
y = (CGFloat) (arc4random() % (int) self.view.bounds.size.height);
point=CGPointMake(x, y);
}
-(BOOL)checkPointExist:(CGPoint)point{
for(UIView *aView in [self.view subviews])
{
if(CGRectContainsPoint(aView.frame, point))
{
return TRUE;// There is already imageview. generate another point
}
}
return FALSE;
}

How to encode a .wmv file that XNA DirectShow will play properly?

I'm playing around with XNA DirectShow to stream a video from a file rather than loading it into my project (I'm fully aware of the XNA MediaPlayer class by the way). It plays the sample video it came with no problem. When I try to make my own .wmv from a series of PNG files I have using ffmpeg the video plays but is all blue (should be mostly yellow). Pixel format wrong? Wrong codec? I'm certainly no expert in these waters..
The sample video is a VC-1 WMV3 apparantly, and I don't think I can replicate that? What encoding/codec/fileformat should I be using?
Also! If transparent video background is possible, that would be amazing. Is it?
Ok I've solved it - I simply switched the order pixels are assigned to when DirectShow creates its output texture. In the VideoPlayer class I changed UpdateBuffer to:
private void UpdateBuffer()
{
int waitTime = avgTimePerFrame != 0 ? (int)((float)avgTimePerFrame / 10000) : 20;
int samplePosRGBA = 0;
int samplePosRGB24 = 0;
while (true)
{
for (int y = 0, y2 = videoHeight - 1; y < videoHeight; y++, y2--)
{
for (int x = 0; x < videoWidth; x++)
{
samplePosRGBA = (((y2 * videoWidth) + x) * 4);
samplePosRGB24 = ((y * videoWidth) + x) * 3;
//make transparent if pixel matches a certain colour
if (WhiteTransparent && bgrData[samplePosRGB24 + 2] > 200 && bgrData[samplePosRGB24 + 1] > 200 && bgrData[samplePosRGB24 + 0] > 200)
{
//transparent pixel
videoFrameBytes[samplePosRGBA + 0] = 0;
videoFrameBytes[samplePosRGBA + 1] = 0;
videoFrameBytes[samplePosRGBA + 2] = 0;
videoFrameBytes[samplePosRGBA + 3] = 0;
}
else
{
//modified pixel format order - switch the 2,1,0 on the right for other formats..
videoFrameBytes[samplePosRGBA + 0] = bgrData[samplePosRGB24 + 2];
videoFrameBytes[samplePosRGBA + 1] = bgrData[samplePosRGB24 + 1];
videoFrameBytes[samplePosRGBA + 2] = bgrData[samplePosRGB24 + 0];
videoFrameBytes[samplePosRGBA + 3] = alphaTransparency;
}
}
}
frameAvailable = false;
while (!frameAvailable)
{ Thread.Sleep(waitTime); }
}
}
which also displays any white areas as transparent in the final image if a bool I added to the class - WhiteTransparent is true. Crude I know, but it's doing the trick for me. Just use the lines in the else statement if not desired.

Per Pixel collision when animate sprites

This is what I have for detecting collision.
public static bool IntersectPixels(Rectangle rectangleA, Color[] dataA, Rectangle rectangleB, Color[] dataB)
{
int top = Math.Max(rectangleA.Top, rectangleB.Top);
int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
int left = Math.Max(rectangleA.Left, rectangleB.Left);
int right = Math.Min(rectangleA.Right, rectangleB.Right);
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];
Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];
if (colorA.A != 0 && colorB.A != 0)
{
return true;
}
}
}
return false;
}:
It work fine until I want to animate stuff. So I have a texture sprite that have about 12 frame. what I need to do is get the color data array of each frame. This is how I get the color data array:
Color[] playerColorArray = new Color[playerColorArray.X * playerColorArray.Y];
PlayerTexture.GetData(playerColorArray);
CData = playerColorArray;
Now my guess is that i have to update the textureData everytime the frame changes
Is there a way to get the the color data from each frame only?
You can get an array of the complete sprite sheet texture and only use the current frame.
Let's say you have a sprite sheet and stride is the offset of a pixel to the pixel below it. This can be the sprite sheet's width. Furthermore, you have the position x0, y0 of the first pixel of the current frame. Then you just have to modify the index calculation:
int posXInFrame = (x - rectangleA.Left);
int posYInFrame = (y - rectangleA.Top);
Color colorA = dataA[(posXInFrame + x0) + (posYInFrame + y0) * stride];
Probably, you have calculated x0 and y0 somewhere else and can pass those values to the function.

Resources