I am trying to work with webcam using C++ and OpenCV in Microsoft Visual Studio Community 2017, but it works very slow(I can't see any changes in video - only one frame). Although the same functions work fine in Python. How can I solve this problem? Thanks.
Mat frame;
VideoCapture vid(0);
if (!vid.isOpened())
{
return -1;
}
else {
while (vid.read(frame))
{
imshow("Video", frame);
if (waitKey() >= 0)
{
break;
}
}
}
return 0;
The problem is the condition waitKey() >= 0.
Change the code to:
Mat frame;
VideoCapture vid(0);
if (!vid.isOpened())
{
return -1;
}
else {
while (vid.read(frame))
{
imshow("Video", frame);
int key = waitKey(1);
if (key == 27)
{
break;
}
}
}
return 0;
waitKey waits the specified time (1) for a key press. In this example we store the value in "key" and if it matches the ascii value 27 (esc key) the program ends.
Why your code does not work:
Your program doesn't seem to work because using waitKey() in C++ it is interpreted as waitKey(0) which will wait forever until some key is pressed (0 means infinite waiting). And when a key is pressed the if sentence (>=0) will become true (because the ascii value of the key pressed will be greater or equal than 0), so the program will exit.
Related
In the code block below I am trying to move a rectangle once for every key-press but the rectangle moves as long as I hold down a key.
ALLEGRO_EVENT ev;
while(!done)
{
al_wait_for_event(event_queue, &ev);
if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_UP:
pos_y -= 10;
break;
case ALLEGRO_KEY_DOWN:
pos_y += 10;
break;
case ALLEGRO_KEY_RIGHT:
pos_x += 10;
break;
case ALLEGRO_KEY_LEFT:
pos_x -= 10;
break;
}
}
else if(ev.type == ALLEGRO_EVENT_KEY_UP)
{
if(ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
done = true;
}
al_draw_filled_rectangle(pos_x, pos_y, pos_x + 30, pos_y + 30, al_map_rgb(255,0,255));
al_flip_display();
al_clear_to_color(al_map_rgb(0,0,0));
}
Also I noticed that al_wait_for_event is not waiting for a new event in case of holding down a key but is in fact making the event of type ALLEGRO_EVENT_KEY_CHAR . Although this should not pose any problem , I wanted to know a bit more about it.
Also, the above code is taken from a tutorial. It worked fine over there.
To make sure your app doesn't apply the key press more than once per Key_Down event define a Boolean initialized to false. Place everything in your Key_Down events in an If statement triggering only if Boolean == false and in its block immediately set Boolean = true followed by the things you want the event to do only once per event.
Then, in the corresponding Key_Up event set
Boolean = false and you should be golden.
I haven't tested this, but it should work, and it serves towards compating your app to any client computer, no matter if they have funky key press settings on their device.
How to find which com-port is occupied by serial mouse
Here is how I detect mouse in C# (adapted code from this answer)
var info = IntPtr.Zero;
try
{
var guid = new Guid("{4d36e96f-e325-11ce-bfc1-08002be10318}"); // mouses
info = SetupDiGetClassDevsW(ref guid, null, IntPtr.Zero, 0);
if ((int)info == -1) // INVALID_HANDLE_VALUE
throw new Exception(string.Format("Error({0}) SetupDiGetClassDevsW", Marshal.GetLastWin32Error()));
// enumerate mouses
var device = new SP_DEVINFO_DATA();
device.cbSize = (UInt32)Marshal.SizeOf(device);
for (uint i = 0; ; i++)
{
// get device info
if (!SetupDiEnumDeviceInfo(info, i, out device))
{
var error = Marshal.GetLastWin32Error();
if (error == 259) // ERROR_NO_MORE_ITEMS
break;
else
throw new Exception(string.Format("Error({0}) SetupDiEnumDeviceInfo", error));
}
string id = GetStringPropertyForDevice(info, device, 1); // SPDRP_HARDWAREID
if (id != null && id.Contains("*PNP0F09")) // Microsoft BallPoint Serial Mouse
{
// ...
// here I want to check com-port, how?
// ...
}
}
}
finally
{
if (info != IntPtr.Zero)
SetupDiDestroyDeviceInfoList(info);
}
Edit
Removing C# tag. Looking for general info (any language).
You can use Process Monitor from SysInternalSuite and open device manager then find out from where does the device manager getting its values
I tried it on USB Mouse and was able to get (on USB Input Device) as shown below
1. Open Mouse Properties (From Control Panel)
2. Open ProcMon
3. Click on the target icon and choose the mouse properties window
4. From the Mouse Properties window open the Hardware tab
5. In ProcMon Click on File-> Captuer Events
6. In ProcMon Edit->Find and look for "com" without quotation mark
7. Double click the found row (If you where able to find it)
Another solution would be to get device information using device manager command line utility devcon and parse the information from the output stream
More information on devcon:
* http://support.microsoft.com/kb/311272
* https://superuser.com/questions/414280/how-do-i-view-a-list-of-devices-from-the-command-line-in-windows
Hope this help
The subroutine that generates the "Location" string in Device Manager is devmgr.dll!GetLocationInformation.
The path in it that interests you - generating the value that is appended in brackets - can be represented with the following code (based on Hex-Rays' decompilation):
int __stdcall GetLocationInformation(DEVINST dnDevInst, wchar_t *lpsResult,
int cchBufferMax, HMACHINE hMachine)
{
int dwUiNumber;
HKEY hKey;
DWORD pulLength;
wchar_t sRawLocationInfo[260];
sRawLocationInfo[0] = 0;
DWORD Type = REG_SZ;
pulLength = 520;
if ( !CM_Open_DevNode_Key_Ex(dnDevInst, KEY_READ, 0, 1u, &hKey, 1u, hMachine) )
{
RegQueryValueExW(hKey, L"LocationInformationOverride", 0, &Type,
sRawLocationInfo, &pulLength);
RegCloseKey(hKey);
}
if ( !sRawLocationInfo[0] )
{
pulLength = 520;
CM_Get_DevNode_Registry_Property_ExW(
dnDevInst,
CM_DRP_LOCATION_INFORMATION,
0,
sRawLocationInfo,
&pulLength,
0,
hMachine);
}
pulLength = 4;
if ( CM_Get_DevNode_Registry_Property_ExW(
dnDevInst,
CM_DRP_UI_NUMBER,
0,
&dwUiNumber,
&pulLength,
0,
hMachine)
|| pulLength <= 0 )
{
<...> //this block always returns
}
else
{
<...>
if ( sRawLocationInfo[0] )
{
lstrcatW(lpsResult, L" (");
lstrcatW(lpsResult, sRawLocationInfo);
lstrcatW(lpsResult, L")");
}
return 0;
}
}
In a nutshell, the bracketed value is the device node's LocationInformationOverride or LocationInformation property and is only produced if the UiNumber property is absent (or bogus).
The CM_Open_DevNode_Key_Ex and CM_Get_DevNode_Registry_Property_ExW functions are marked "reserved" in the docs. You can
find their signatures e.g. in CM_Open_DevNode_Key_Ex - FileLog and Enumerate Properties of an Installed Device - The Code Project, respectively, or
use the publicly-documented CM_Open_DevNode_Key and CM_Get_DevNode_Registry_Property instead. They are exactly the same as the former ones save for missing the hMachine argument (they essentially directly call them substituting NULL for it).
There are corresponding SetupDi equivalents, SetupDiOpenDevRegKey and SetupDiGetDeviceRegistryProperty, as well but note that this API is new in Vista and uses different data types.
Seeing that you use it already though means that this is probably the way to go for you unless you need XP support.
If my guess is right, the "USB Serial Port (COM6)" you see in Device Manager is actually the name of the parent device (=the device this one is connected to as seen in Device Manager in "view devices by connection" mode). If this is correct, the "COM6" is but a part of the name rather than some independent property.
I've searched the net, I've searched here. I've found code that I could compile and it works fine, but for some reason my code won't produce any sound. I'm porting an old game to the PC (Windows,) and I'm trying to make it as authentic as possible, so I'm wanting to use generated wave forms. I've pretty much copied and pasted the working code (only adding in multiple voices,) and it still won't work (even thought the exact same code for a single voice works fine.) I know I'm missing something obvious, but I just cannot figure out what. Any help would be appreciated thank you.
First some notes... I was looking for something that would allow me to use the original methodology. The original system used paired bytes for music (sound effects - only 2 - were handled in code.) A time byte that counted down every time the routine was called, and a note byte that was played until time reached zero. this was done by patching into the interrupt vector, windows doesn't allow that, so I set up a timer that routing that accomplished the same thing. The timer kicks in, updates the display, and then runs the music sequence. I set this up with a defined time so that I only have one place to adjust the timing at (to get it as close as possible to the original sequence. The music is a generated wave form (and I've double checked the math, and even examined the generated data in debug mode,) and it looks good. The sequence looks good, but doesn't actually produce sound. I tried SDL2 first, and it's method of only playing 1 sound doesn't work for me, also, unless I make the sample duration extremely short (and the sound produced this way is awful,) I can't match the timing (it plays the entire sample through it's own interrupt without letting me make adjustments.) Also, blending the 3 voices together (when they all run with different timings,) is a mess. Most of the other engines I examined work in much the same way, they want to use their own callback interrupt and won't allow me to tweak it appropriately. This is why I started working with OpenAL. It allows multiple voices (sources,) and allows me to set the timings myself. On advice from several forums, I set it up so that the sample lengths are all multiples of full cycles.
Anyway, here's the code.
int main(int argc, char* argv[])
{
FreeConsole(); //Get rid of the DOS console, don't need it
if (InitLog() < 0) return -1; //Start logging
UINT_PTR tim = NULL;
SDL_Event event;
InitVideo(false); //Set to window for now, will put options in later
curmusic = 5;
InitAudio();
SetTimer(NULL,tim,_FREQ_,TimerProc);
SDL_PollEvent(&event);
while (event.type != SDL_KEYDOWN) SDL_PollEvent(&event);
SDL_Quit();
return 0;
}
void CALLBACK TimerProc(HWND hWind, UINT Msg, UINT_PTR idEvent, DWORD dwTime)
{
RenderOutput();
PlayMusic();
//UpdateTimer();
//RotateGate();
return;
}
void InitAudio(void)
{
ALCdevice *dev;
ALCcontext *cxt;
Log("Initializing OpenAL Audio\r\n");
dev = alcOpenDevice(NULL);
if (!dev) {
Log("Failed to open an audio device\r\n");
exit(-1);
}
cxt = alcCreateContext(dev, NULL);
alcMakeContextCurrent(cxt);
if(!cxt) {
Log("Failed to create audio context\r\n");
exit(-1);
}
alGenBuffers(4,Buffer);
if (alGetError() != AL_NO_ERROR) {
Log("Error during buffer creation\r\n");
exit(-1);
}
alGenSources(4, Source);
if (alGetError() != AL_NO_ERROR) {
Log("Error during source creation\r\n");
exit(-1);
}
return;
}
void PlayMusic()
{
static int oldsong, ofset, mtime[4];
double freq;
ALuint srate = 44100;
ALuint voice, i, note, len, hold;
short buf[4][_BUFFSIZE_];
bool test[4] = {false, false, false, false};
if (curmusic != oldsong) {
oldsong = (int)curmusic;
if (curmusic > 0)
ofset = moffset[(curmusic - 1)];
for (voice = 1; voice < 4; voice++)
alSourceStop(Source[voice]);
mtime[voice] = 0;
return;
}
if (curmusic == 0) return;
//Only 3 voices for music, but have
for (voice = 0; voice < 3; voice ++) { // 4 set asside for eventual sound effects
if (mtime[voice] == 0) { //is note finished
alSourceStop(Source[voice]); //It is, so stop the channel (source)
mtime[voice] = music[ofset++]; //Get the next duration
if (mtime[voice] == 0) {oldsong = 0; return;} //zero marks end, so restart
note = music[ofset++]; //Get the next note
if (note > 127) { //Old HW data was designed for could only
if (note == 255) note = 127; //use values 128 - 255 (255 = 127)
freq = (15980 / (voice + (int)(voice / 3))) / (256 - note); //freq of note
len = (ALuint)(srate / freq); //A single cycle of that freq.
hold = len;
while (len < (srate / (1000 / _FREQ_))) len += hold; //Multiply till 1 interrup cycle
while (len > _BUFFSIZE_) len -= hold; //Don't overload buffer
if (len == 0) len = _BUFFSIZE_; //Just to be safe
for (i = 0; i < len; i++) //calculate sine wave and put in buffer
buf[voice][i] = (short)((32760 * sin((2 * M_PI * i * freq) / srate)));
alBufferData(Buffer[voice], AL_FORMAT_MONO16, buf[voice], len, srate);
alSourcei(openAL.Source[i], AL_LOOPING, AL_TRUE);
alSourcei(Source[i], AL_BUFFER, Buffer[i]);
alSourcePlay(Source[voice]);
}
} else --mtime[voice];
}
}
Well, it turns out there were 3 problems with my code. First, you have to link the built wave buffer to the AL generated buffer "before" you link the buffer to the source:
alBufferData(buffer,AL_FORMAT_MONO16,&wave_sample,sample_lenght * sizeof(short),frequency);
alSourcei(source,AL_BUFFER,buffer);
Also in the above example, I multiplied the sample_length by how many bytes are in each sample (in this case "sizeof(short)".
The final problem was that you need to un-link a buffer from the source before you change the buffer data
alSourcei(source,AL_BUFFER,NULL);
The music would play, but not correctly until I added that line to the note change code.
So, here is a countdown.
My aim is the next: if you don't do anything for the given time (ent_sec) the countdown will reach 0 after a time and return with 0, BUT if you press down the letter c (code: 99) the countdown stops and you can enter your PIN code and return with it.
I have already solved the problem with Windows.h in the next way:
if (GetAsyncKeyState(VK_SPACE))
This solves the problem is through WIN32 API (in this case you have to press SPACE, not letter 'c'), but it revealed that I can't use any WinAPI function (school project). So I rewrite this line to the following:
if (getchar() == 99)
But unfortunately it doesn't work in the proper way, cause my countdown stops in almost every second until I dont't press some "wrong" key (for example I press 'x', then the countdown goes forward, but in the next sec it stops again)... In the first solution (win func) this problem doesn't exist... So how can I fix that? Thanks. Here is the whole code of my function:
unsigned Timer::DownCount
{
int ent_sec = this.time;
cout << "The counter has started (" << this.time << "sec), press 'C' to enter your PIN code: " << endl;
while (ent_sec >= 0)
{
if (getchar() == 99) // c letter's code is 99 in ANSI (or ASCII dunno)
{
unsigned code;
cout << "PIN code: ";
cin >> code;
return code;
}
else
{
SecCounter(1); // this function counts 1 secundum
cout << ent_sec << endl;
ent_sec--;
}
}
return 0;
}
I don't believe there's a standard way to do this that will work across all platforms, but here's one way of doing it that will work on Windows without actually using Windows API functions.
int getch_nowait()
{
if (!kbhit()) return -1;
return getch();
}
Then your check just becomes if (getch_nowait() == 99) ...
This code may be compiler specific. If it doesn't work for you, it'll help if you tell us what compiler and operating system you are using.
Visual Studio gives many navigation hotkeys:
F8 for next item in current panel (search results, errors ...),
Control+K, N for bookmarks,
Alt+- for going back and more.
There is one hotkey that I can't find, and I can't even find the menu-command for it, so I can't create the hotkey myself.
I don't know if such exist: Previous and Next call-stack frame.
I try not using the mouse when programming, but when I need to go back the stack, I must use it to double click the previous frame.
Anyone? How about a macro that does it?
I wrote 2 macros to gain it: PreviousStackFrame and NextStackFrame and assigned shortcuts to
Function StackFrameIndex(ByRef aFrames As EnvDTE.StackFrames, ByRef aFrame As EnvDTE.StackFrame) As Long
For StackFrameIndex = 1 To aFrames.Count
If aFrames.Item(StackFrameIndex) Is aFrame Then Exit Function
Next
StackFrameIndex = -1
End Function
Sub NavigateStack(ByVal aShift As Long)
If DTE.Debugger.CurrentProgram Is Nothing Then
DTE.StatusBar.Text = "No program is currently being debugged."
Exit Sub
End If
Dim ind As Long = StackFrameIndex(DTE.Debugger.CurrentThread.StackFrames, DTE.Debugger.CurrentStackFrame)
If ind = -1 Then
DTE.StatusBar.Text = "Stack navigation failed"
Exit Sub
End If
ind = ind + aShift
If ind <= 0 Or ind > DTE.Debugger.CurrentThread.StackFrames.Count Then
DTE.StatusBar.Text = "Stack frame index is out of range"
Exit Sub
End If
DTE.Debugger.CurrentStackFrame = DTE.Debugger.CurrentThread.StackFrames.Item(ind)
DTE.StatusBar.Text = "Stack frame index: " & ind & " of " & DTE.Debugger.CurrentThread.StackFrames.Count
End Sub
Sub PreviousStackFrame()
NavigateStack(1)
End Sub
Sub NextStackFrame()
NavigateStack(-1)
End Sub
I have solved this problem with AutoHotkey. I made this a few months ago.
Suppose you wanted to use Control+1 and Control+2 and that Control+Alt+C is bound to showing the Call Stack window:
^1::SendInput !^c{down}{enter}
^2::SendInput !^c{up}{enter}
It seems to work pretty well. If you aren't already using AutoHotkey to show Visual Studio who's boss, please give it a shot. Your question indicates that you would benefit greatly from it. It's a game changer. Good luck.
I don't think theres an explict next-frame / prev-frame key binding but heres what I do.
CTRL-ALT-C is already bound to "Debug.CallStack"
This will focus you in the Call Stack Tool Window
Once focused in the Callstack window... Up & Down arrows will move you through the call stack frames
I've then bound
CTRL-C, CTRL-S to "DebuggerContextMenus.CallStackWindow.SwitchToFrame"
and
CTRL-C, CTRL-C to "DebuggerContextMenus.CallStackWindow.SwitchToCode"
both of which will take you back into the code window at the particular frame.
Hope that helps.
Huge thanks to #Oleg Svechkarenko for his answer that gave me a starting point in crafting this solution. Since modern versions of Visual Studio no longer have official macro support, this should drop in for those who use the Visual Commander plugin, but probably can be easily adapted for any other macro extension.
Here is the code for the command, I created one for navigating up the call stack and one for navigating down with the same code except the parameter passed to MoveStackIndex(), then bound keyboard shortcuts to them:
using EnvDTE;
using EnvDTE80;
using System;
public class C : VisualCommanderExt.ICommand
{
enum MoveDirection
{
Up,
Down,
}
private bool IsValidFrame(StackFrame frame)
{
string language = frame.Language;
bool result = (language == "C#" ||
language == "C++" ||
language == "VB" ||
language == "Python");
return result;
}
private void MoveStackIndex(EnvDTE80.DTE2 DTE, MoveDirection direction)
{
StackFrame currentFrame = DTE.Debugger.CurrentStackFrame;
bool foundTarget = false;
bool pastCurrent = false;
StackFrame lastValid = null;
foreach (StackFrame frame in DTE.Debugger.CurrentThread.StackFrames)
{
bool isCurrent = frame == currentFrame;
if (direction == MoveDirection.Down)
{
if (isCurrent)
{
if (lastValid == null)
{
// No valid frames below this one
break;
}
else
{
DTE.Debugger.CurrentStackFrame = lastValid;
foundTarget = true;
break;
}
}
else
{
if (IsValidFrame(frame))
{
lastValid = frame;
}
}
}
if (direction == MoveDirection.Up && pastCurrent)
{
if (IsValidFrame(frame))
{
DTE.Debugger.CurrentStackFrame = frame;
foundTarget = true;
break;
}
}
if (isCurrent)
{
pastCurrent = true;
}
}
if (!foundTarget)
{
DTE.StatusBar.Text = "Failed to find valid stack frame in that direction.";
}
}
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
if (DTE.Debugger.CurrentProgram == null)
{
DTE.StatusBar.Text = "Debug session not active.";
}
else
{
// NOTE: Change param 2 to MoveDirection.Up for the up command
MoveStackIndex(DTE, MoveDirection.Down);
}
}
}
Look in Tools->Options->Environment->Keyboard. Enter "stack" or "frame" and related menus will appear. It seems that there's no next and previous call-stack frame.