Vb.Net : Dynamically create rectangles in a picturebox side by side - drawing

I am current working on an application in which I am using a video stream eventhandler to produce a camera image in a Forms picturebox in VB.Net (yes it sounds like a kinect app...it is...)
I can create a red rectangle over my bitmap image (camer stream) using this code:
Dim g As Graphics = Graphics.FromImage(kinectVideoBitMap)
Dim rect As Rectangle = New Rectangle
rect.Width = 6.4
rect.Height = 480
g.DrawRectangle(Pens.Red, rect)
End If
Straight forward enough.
But, what I really would like to happen is to be able to create multiple rectangles side by side crossing the width of my picture box at "6.4" (<--pixels I think??)
I have attempted using a "For Loop" to create these rectangles and then setting a new location for each one, like this:
Dim g As Graphics = Graphics.FromImage(kinectVideoBitMap)
Dim i As Integer
For i = 0 To 100
Dim rect As Rectangle = New Rectangle
rect.Width = 6.4
rect.Height = 480
rect.Location = New System.Drawing.Point(*{not sure how to measure here}*, *{or here either}*)
g.DrawRectangle(Pens.Red, rect)
Next
Any help would be wonderful.
My plan is to use these rectangles to help me choose skeletons to monitor chosen by the microphone array sound source position. Hence the rectangles width of "6.4"
640 is the Width resolution of the video stream, and I divided it by "100" the measure of "-50 to 50" in the microphone array.
But, in the end I just need help with the rectangles.
EDIT: Here is something here that I have come up with. I am now very close to an answer:
Dim g As Graphics = Graphics.FromImage(kinectVideoBitMap)
Dim i As Integer = 1
Dim newLocationX As Integer = 0
Do Until i = 100
Dim rect(i) As Rectangle
Rect(i) = New Rectangle
Rect(i).Width = 6
Rect(i).Height = 480
Rect(i).Location = New System.Drawing.Point(video.Left + newLocationX, Rect(i).Location.Y)
g.DrawRectangle(Pens.Red, Rect(i))
newLocationX = newLocationX + 6
i += 1
Loop
End If
Last Edit: My math was way way wrong. Here is how I got it to work:
The resolution of the image width is 640
I needed to fill the width with 100 rectangles.
The math is 640 / 100 = 6.4 <-- the width of the rectangles
I thought that I had to repeat the For Loop 100 times to get 100 rectangles. this is not true. Repeat the For Loop the width of the picture box: 640 times!
The fact that you place rectangles in the picture box at a width 6.4 will automatically create 100 rectangles in a picture box with a width of 640.
here is the code that works:
Dim g As Graphics = Graphics.FromImage(kinectVideoBitMap)
Dim i As Integer = 0
Dim newLocationX As Integer = 0
Do Until i = 640
Dim rect(i) As Rectangle
rect(i) = New Rectangle
rect(i).Width = 6.4
rect(i).Height = 480
rect(i).Location = New System.Drawing.Point(video.Right - newLocationX, rect(i).Location.Y)
g.DrawRectangle(Pens.Red, rect(i))
newLocationX = newLocationX + 6.4
i += 1
Loop

Related

Is there a way to stretch or alter text size? C++

I am making a game in c++ using ASCII and I need to stretch/shrink the text because everything is stretched on the Y axis
Example:
I have tried SetConsoleTextAttribute, but if I set the x and y to try to adjust the text it only scales it aka X and Y together.
Current Code:
HANDLE m_hConsole;
void ASCIIRenderer::InitialisePixelSize(int fontx, int fonty)
{
PCONSOLE_FONT_INFOEX font_size = new CONSOLE_FONT_INFOEX();
font_size->cbSize = sizeof(CONSOLE_FONT_INFOEX);
GetCurrentConsoleFontEx(m_hConsole, false, font_size);
font_size->dwFontSize.X = fontx; //Width of element in buffer
font_size->dwFontSize.Y = fonty; //Hieght of element in buffer
SetCurrentConsoleFontEx(m_hConsole, false, font_size); //Set the new font size
}
Is there a way to alter the X or Y to effectively stretch/shrink the text?

How do I find an object in image/video knowing its real physical dimension?

I have a sample of images and would like to detect the object among others in the image/video already knowing in advance the real physical dimensions of that object. I have one of the image sample (its airplane door) and would like to find the window in the airplane door knowing its physical dimensions(let we say it has inner radius of 20cm and out radius of 23cm) and its real world position in the door (for example its minimal distance to the door frame is 15cm) .Also I can know prior my camera resolution. Any matlab code or OpenCV C++ that can do that automatically with image processing?
Here is my image sample
And more complex image with round logos.
I run the code for second complex image and do not get the same results. Here is the image result.
You are looking for a circle in the image so i suggest you use Hough circle transform.
Convert image to gray
Find edges in the image
Use Hugh circle transform to find circles in the image.
For each candidate circle sample the values of the circle and if the values corresponds to a predefined values accept.
The code:
clear all
% Parameters
minValueWindow = 90;
maxValueWindow = 110;
% Read file
I = imread('image1.jpg');
Igray = rgb2gray(I);
[row,col] = size(Igray);
% Edge detection
Iedge = edge(Igray,'canny',[0 0.3]);
% Hough circle transform
rad = 40:80; % The approximate radius in pixels
detectedCircle = {};
detectedCircleIndex = 1;
for radIndex=1:1:length(rad)
[y0detect,x0detect,Accumulator] = houghcircle(Iedge,rad(1,radIndex),rad(1,radIndex)*pi/2);
if ~isempty(y0detect)
circles = struct;
circles.X = x0detect;
circles.Y = y0detect;
circles.Rad = rad(1,radIndex);
detectedCircle{detectedCircleIndex} = circles;
detectedCircleIndex = detectedCircleIndex + 1;
end
end
% For each detection run a color filter
ang=0:0.01:2*pi;
finalCircles = {};
finalCircleIndex = 1;
for i=1:1:detectedCircleIndex-1
rad = detectedCircle{i}.Rad;
xp = rad*cos(ang);
yp = rad*sin(ang);
for detectedPointIndex=1:1:length(detectedCircle{i}.X)
% Take each detected center and sample the gray image
samplePointsX = round(detectedCircle{i}.X(detectedPointIndex) + xp);
samplePointsY = round(detectedCircle{i}.Y(detectedPointIndex) + yp);
sampleValueInd = sub2ind([row,col],samplePointsY,samplePointsX);
sampleValueMean = mean(Igray(sampleValueInd));
% Check if the circle color is good
if(sampleValueMean > minValueWindow && sampleValueMean < maxValueWindow)
circle = struct();
circle.X = detectedCircle{i}.X(detectedPointIndex);
circle.Y = detectedCircle{i}.Y(detectedPointIndex);
circle.Rad = rad;
finalCircles{finalCircleIndex} = circle;
finalCircleIndex = finalCircleIndex + 1;
end
end
end
% Find Main circle by merging close hyptosis together
for finaCircleInd=1:1:length(finalCircles)
circleCenter(finaCircleInd,1) = finalCircles{finaCircleInd}.X;
circleCenter(finaCircleInd,2) = finalCircles{finaCircleInd}.Y;
circleCenter(finaCircleInd,3) = finalCircles{finaCircleInd}.Rad;
end
[ind,C] = kmeans(circleCenter,2);
c = [length(find(ind==1));length(find(ind==2))];
[~,maxInd] = max(c);
xCircle = median(circleCenter(ind==maxInd,1));
yCircle = median(circleCenter(ind==maxInd,2));
radCircle = median(circleCenter(ind==maxInd,3));
% Plot circle
imshow(Igray);
hold on
ang=0:0.01:2*pi;
xp=radCircle*cos(ang);
yp=radCircle*sin(ang);
plot(xCircle+xp,yCircle+yp,'Color','red', 'LineWidth',5);
The resulted image:
Remarks:
For other images will still have to fine tune several parameters like the radius that you search for the color and Hough circle threshold and canny edge thresholds.
In the function i searched for circle with radius from 40 pixels to 80. In here you can use your prior information about the real world radius of the window and the resolution of the camera. If you know approximately the distance the camera was from the airplane and the resolution of the camera and also the window radius in cm you can use this to get the radius in pixels and use this for the hough circle transform.
I wouldn't worry too much about the exact geometry and calibration and rather find the window by its own characteristics.
Binarization works relatively well, be it on the whole image or in a large region of interest.
Then you can select the most likely blob based on it approximate area and/or circularity.

Program crashes, because of std::rotate_copy

I am trying to display two cams next to each other, rotated by 90°. Displaying both cams works fine, but if I want to rotate the cams, the program crashes.
The camera is read with a QByteArray and shown with the QCamera variable.
You can choose which camera is displayed in which viewfinder, so it has a code like this:
QActionGroup *videoDevicesGroup = new QActionGroup(this);
videoDevicesGroup->setExclusive(true);
foreach(const QByteArray &deviceName, QCamera::availableDevices()) {
QString description = camera->deviceDescription(deviceName);
QAction *videoDeviceAction = new QAction(description, videoDevicesGroup);
videoDeviceAction->setCheckable(true);
videoDeviceAction->setData(QVariant(deviceName));
if (cameraDevice.isEmpty()) {
cameraDevice = deviceName;
videoDeviceAction->setChecked(true);
}
ui->menuDevices->addAction(videoDeviceAction);
}
connect(videoDevicesGroup, SIGNAL(triggered(QAction*)), SLOT(updateCameraDevice(QAction*)));
if (cameraDevice.isEmpty())
{
camera = new QCamera;
}
else
{
camera = new QCamera(cameraDevice);
}
connect(camera, SIGNAL(stateChanged(QCamera::State)), this, SLOT(updateCameraState(QCamera::State)));
connect(camera, SIGNAL(error(QCamera::Error)), this, SLOT(displayCameraError()));
camera->setViewfinder(ui->viewfinder);
updateCameraState(camera->state());
camera->start();
Now I'm trying to rotate this cam with the command:
std::roate_copy(cameraDevice.constBegin(), cameraDevice.constEnd(), cameraDevice.constEnd, reverse.begin());
camera = new QCamera(reverse);
But when I try to start the program the program crashes, without any errors.
How can I fix this?
I think you have a misunderstanding on what std::rotate_copy does.
std::rotate_copy takes a range of data and shifts it as it copies into the location pointed to by the result iterator.
This won't rotate a camera. It just shifts and copies ranges: http://www.cplusplus.com/reference/algorithm/rotate_copy
EDIT:
Think about it this way say I have: std::string("wroybgivb");
Now say I do str::rotate_copy and I pick the "y" as my middle the std::string that I copied into will contain "ybgivbwro".
Now think about that like I was working with a 3X3 image and each character represented a color:
wro ybg
ybg => ivb
ivb wro
Note that this is doing a linear array rotation (position shifting). I can never pick a middle such that rows will become columns and columns will become rows.
PS:
OK so say that you knew the width of the image, and assigned it to the variable width. You can do something like this to rotate 90° clockwise:
for(int x = 0; x < size; ++x){
output[width - 1 - i / width + (i % width) * width] = input[i];
}
To understand this you need to understand indexing a linear array as though it's a 2D array.
Use this to access the x coordinate: i % width
Use this to access the y coordinate: (i / width) * width
Now you need to take those indices and rotate them still inside a linear array.
Use this to access the x coordinate: width - 1 - i / width
Use this to access the y coordinate: (i % width) * width

center the text inside the object and adjust the size according to the width and height of the object

I have a rectangle object that is being displayed with the width 50 and height 100.
I have a text label that i want to center inside the rectangle on the sceen and adjust the size of
the text according ( the size of text range from 0-100+) to the size of the rectangle.
Here what i'm doing:
int rectangle_width = 50;
int rectangle_height = 100;
// i'm calculating the center of the rectangle
text_x_positon = rectangle_width/2;
text_y_positon = rectangle_height/2;
// calculating the size of the text label according to rectangle free space
int size = (rectangle_width/rectangle_height)*10;
label(text_x_positon, text_y_positon, size);
The problem is that sometimes the text is smaller or bigger than the rectangle, please help me to solve this problem and show me the correct way of doing it.

Drawing Image in centre while maintaining the Aspect Ratio

Part 1 : In one of my projects, I want to display a Image in center of a Custom Control using GDI+ while maintaining the aspect ratio of the Image. Here is my code
Gdiplus::Image image(imagePathWStr); // imagePathWStr is the Image Path
int originalWidth = image.GetWidth();
int originalHeight = image.GetHeight();
// This code calculates the aspect ratio in which I have to draw the image
int16 cntrlwidth = controlPosition.right - controlPosition.left; // controlPosition is the custom Control Rect
int16 cntrlheigth = controlPosition.bottom - controlPosition.top;
float percentWidth = (float)cntrlwidth / (float)originalWidth;
float percentHeight = (float)cntrlheigth / (float)originalHeight;
float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
int newImageWidth = (int)(originalWidth * percent);
int newImageHeight = (int)(originalHeight * percent);
Gdiplus::RectF imageContainer;
imageContainer.X = controlPosition.left;
imageContainer.Y = controlPosition.top;
imageContainer.Width = controlPosition.right;
imageContainer.Height = controlPosition.bottom;
Gdiplus::Graphics gdiGraphics(hDC);
Gdiplus::Unit scrUnit = Gdiplus::UnitPixel;
gdiGraphics.DrawImage(&image, imageContainer, 0, 0, originalWidth, originalHeight, scrUnit);
However when the Control is resized vertically the image is moving to the right and not always stay in center, Also when Control is resized Horizontally, it is moving to the bottom. I am not able to figure out why.
I am using C++ on Windows.
Part 2: Now I have got a Rectangle drawn as well on top of this
Gdiplus::RectF cropRect;
cropRect.X = 100;
cropRect.Y = 100;
cropRect.Width = 300;
cropRect.Height = 300;
Gdiplus::Pen* myPen = new Gdiplus::Pen(Gdiplus::Color::White);
myPen->SetWidth(3);
gdiGraphics.DrawRectangle(myPen, cropRect);
Now When I resize the Control, Image is getting resized correctly but this rectangle is not, I multiplied Width and Height accordingly
Gdiplus::RectF cropRectangle;
cropRectangle.X = cropRect.GetLeft();
cropRectangle.Y = cropRec.GetTop();
cropRectangle.Width = (cropRec.Width)* percent;
cropRectangle.Height = (cropRec.Height ) * percent;
My Part 1 has been solved after Adrians Answer now I am stuck on Part 2 of my problems
Thanks
-Pankaj
when the size of the control changes you'll have a WM_SIZE message posted to your window. you must refresh your aspect ratio according to new size.