opencv : Unable to read upper case letters through waitKey - c++

I have a simple switch case as follows inside an infinite while loop, to call functions based on the key pressed by the user. I am programming in C++ using opencv libraries.
The waitKey function used below is able to read the lower case letters i press on the keyboard. I am however unable to read any upper case letters and it still reads and interprets it as the corresponding lower case letter.
Any help in this regard is appreciated. should i be updating my opencv libraries? I installed opencv on ubuntu with the help of this post
os UBUNTU 13.10
opencv version 2.4.8
Pseudo code
while(1)
{`
char k = waitKey(0);
switch(k) {
case 'a' : ... break;
case 'b' : ... break;
case 'A' : ... break; // UNABLE TO READ A here.
}
}

I found a small hint related to your problem on OpenCV forum incase you have not found it yet: http://answers.opencv.org/question/4266/cvwaitkey-upper-lowercase-difference/

I have the same problem (with opencv-4.x).
I think this is due to the fact that I compiled opencv with the cmake option -D WITH_QT=ON (to enable the zoom scroll on images). But Qt interprets q and Q as the same keycode (81); the only thing is that it adds a (shift) modifier.
Let's say you receive a QKeyEvent event in a C++/Qt program. Then you get when pressing:
'Q': event.key() = 81, event.modifiers().testFlag(Qt::KeyboardModifier::ShiftModifier) = true
'q': event.key() = 81, event.modifiers().testFlag(Qt::KeyboardModifier::ShiftModifier) = false
It seems cv::waitKey or cv::waitKeyEx, when opencv uses Qt, does not read the modifiers, just the key code, unfortunately...
So far, the only option I found is to recompile with -D WITH_QT=OFF. Then I can discriminate between Q and q (but also left arrow and Shifted left arrow and so on). But the trade-off is that I can't scroll the images anymore...

Related

Can I get character from keyboard without pausing a program

I'm working on a little project to improve my coding skills and I have a problem. I'm doing a console version of Flappy Bird. So i have a map which is a two-dimensional array of chars and this map have to move to the left. I am moving all elements of an array one place to the left and after that, clearing console and showing moved map. And here is problem, map has to move constantly but player have to control a bird while map is moving. I wanted to use _getch() but it pausing a program. A question is: Can i read a keyboard input without pausing program? I mean that the map will still moving and when i press for example Space in any moment the bird position will change. I'm working on Windows 10
Even if beginners hope it to be a simple operation, inputting a single character from the keyboard is not, because in current Operating Systems, the keyboard is by default line oriented.
And peeking the keyboard (without pausing the program) is even harder. In a Windows console application, you can try to use functions from user32, for example GetAsyncKeyState if you only need to read few possible keys: you will know if the key is currently pressed and whether if was pressed since the last call to GetAsyncKeyState.
But beware: these are rather advanced system calls and I strongly advise you not to go that way if you want to improve your coding skills. IMHO you'd better learn how to code Windows GUI applications first because you will get an event loop, and peeking for events is far more common and can be used in real world applications. While I have never seen a real world console application trying to peek the keyboard. Caveat emptor...
Including conio.h
you can use this method:
#define ARROW_UP 72
#define ARROW_DOWN 80
#define ARROW_LEFT 75
#define ARROW_RIGHT 77
int main(){
int key;
while( true ){
if( _kbhit() ){ // If key is typed
key = _getch(); // Key variable get the ASCII code from _getch()
switch( key ){
case ARROW_UP:
//code her...
break;
case ARROW_DOWN:
//code her...
break;
case ARROW_LEFT:
//code her...
break;
case ARROW_RIGHT:
//code her...
break;
default:
//code her...
break;
}
}
}
return 0;
}
The upper code is an example, you can do this for any key of keyboard. In this sites you can find the ASCII code of keys:
http://www.jimprice.com/jim-asc.shtml#keycodes
https://brebru.com/asciicodes.html
Say me if it has help you!

OpenCV destroyWindow() not working with multiple windows

I am using openCV library to open and display multiple images. I am doing this with multiple windows created in order to display each image. In order to achieve display of multiple windows at the same time, I am using waitKey() only after the last image.
cv::namedWindow("Window1");
cv::imshow("Window1", myImage1);
cv::namedWindow("Window2");
cv::imshow("Window2", myImage2);
cv::waitKey(1000);
As can be seen from the code, my goal is to give the user 1s of time to press any key, otherwise I want to destroy one of the windows (for the purpose of this question it can be either one). I want to achieve this by using openCV's function destroyWindow().
Below my entire code can be seen:
cv::namedWindow("Window1");
cv::imshow("Window1", myImage1);
cv::namedWindow("Window2");
cv::imshow("Window2", myImage2);
cv::waitKey(1000);
cv::destroyWindow("Window2");
The goal of this code snippet should be that only "Window1" remains displayed, if 1s goes by, with the user not pressing any key.
However, this does not happen. The end result is that none of the windows are destroyed.
I have tested the following code snippet, which results in both windows being closed:
cv::namedWindow("Window1");
cv::imshow("Window1", myImage1);
cv::namedWindow("Window2");
cv::imshow("Window2", myImage2);
cv::waitKey(1000);
cv::destroyWindow("Window1");
cv::destroyWindow("Window2");
The same results when I use destroyAllWindows() function (which makes sense).
My question now is, why can't I destroy only one of the windows?
Additional info:
Using Ubuntu 20.04.
OpenCV version is 4.2.
Working in C++
Changing the order of which window I want to destroy changes nothing.
Tried to replicate it, facing this issue in Python as well on Ubuntu. If you are still stuck, you can try a stopgap solution of reshowing only the one you wanted to show provided the user has pressed a key or not by storing the result of waitKey in some variable. If it is -1 then no key has been pressed.
I have provided a sample solution in Python which you shouldn't face any difficulties converting to C++.
import cv2
img1 = cv2.imread('img1.png')
img2 = cv2.imread('img2.png')
cv2.namedWindow('img1')
cv2.imshow('img1', img1)
cv2.namedWindow('img2')
cv2.imshow('img2', img2)
key = cv2.waitKey(5000)
if key == -1:
cv2.destroyAllWindows()
cv2.imshow('img1', img1)
cv2.waitKey(0)
else:
# do whatever destroy both or keep on showing both using cv2.waitKey(0)
cv2.destroyAllWindows()
I have reached a solution by adding startWindowThread() before adding each of the windows.
An important thing to note is also that I have built openCV using GTK option, so my solution is tested only on GTK not on others.
startWindowThread() is used only with GTK as noted here: https://github.com/opencv/opencv/issues/7562 - for others the function is empty.

C++: OpenCV2.4.11(!) access to webcam parameters

This is a direct follow-up of the last question I asked which was aptly named "C++: OpenCV2.3.1(!) access to webcam parameters" and where I was told to install OpenCV2.4.11 instead (OpenCV3.0 did not work)... which I did. And yes, most of this text is an exact copy&paste of the last thread since my problem hasn't actually vanished...
Again, I've searched here, on other forums (Google, OpenCV etc), looked at the code of the videoInput library, the different header files and especially OpenCV's highgui_c.h and still seem to be unable to find an answer to this very simple question:
How do I change exposure and gain (or, to be general, any webcam property) in my Logitech C310 webcam with OpenCV2.4.11 the same way I was able to with OpenCV2.1.0? (using Win7 64-bit, Visual Studio 10)
EDIT: This has been solved. I do not know how but when I tested my code this morning it was able to report and set the exposure using VideoCapture and the set/get method.
There's the nice and easy VideoCapture get and set method, I know, similar to the videoInput's [Set/Get]VideoSetting[Camera/Filter] functions. Here's my short example in OpenCV2.4.11 that doesn't work:
EDIT: It does work now. What I don't understand is that the values of several properties are reported as -8.58993E+008 (namely hue, monocrome, gamma, temperature, zoom, focus, pan, tilt, roll and iris) and that property 6 (fourcc) is -4.66163E+008. I know I don't have these features on my webcam but all other unimplemented features report -1.
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* CmdArgs, int CmdShow) {
int device0 = 0;
VideoCapture VC(device0);
if(!VC.isOpened()) // check if we succeeded
return -1;
ostringstream oss;
double CamProp;
for(int i=-4; i<27; i++) {
CamProp = VC.get(i);
Sleep(5);
oss << "Item " << i << ": " << CamProp << "\n";
}
MessageBox(NULL, oss.str().c_str(), "Webcam Values", MB_OK);
return 0;
}
It compiles, it runs, it accesses the webcam alright (and even shows a picture with imshow if I add it to the code) but it only opens a nice window saying this:
Item -4: 0
Item -3: 0
Item -2: 0
...
Item 2: 0
Item 3: 640
Item 4: 480
Item 5: 0
...
Item 25: 0
Item 26: 0
EDIT: See above, this works now. I get values for all supported parameters like exposure, gain, sharpness, brightness, contrast and so on. Perhaps I was still linking to the 2.3.1 libraries or whatever.
The point is: This was all perfectly settable with this camera under OpenCV 2.1.0 using videoInput. I had a running application doing its own lighting instead of using the Logitech functions (RightLight, Auto Exposure, Auto Whitebalance). Now setting and getting the parameters has been integrated into OpenCV highgui for quite a while but with a strongly reduced feature list (no requesting of parameter ranges, Min/Max/Stepwidth..., no setting of auto exposure, RightLight and similar stuff) and for some reason it's incompatible with my Logitech webcam. I can report the resolution but nothing else.
EDIT: I still miss the Min, Max, Step, Auto/Manual features of videoInput. I can set a value but I don't know whether it's allowed.
The videoInput code is now merged into OpenCV's code in the file cap_dshow.cpp but I can't find a header file that declares the videoInput class and simply using my old code doesn't work. So I have a cpp file which contains all functions I need and which I know did the job for me a while back but which I can't access now. Any clues on how to do that? Has anyone accessed and changed camera parameters in OpenCV2.4.11 using the videoInput/DirectShow interface?
EDIT: Seems this has happened now in a working way, unlike 2.3.1. No direct interaction with videoInput seems to be needed. However it would be nice to have it for the aforementioned reasons.
There's also the funny problem that using e.g.
VideoCapture cam(0)
addresses exactly the same camera as
VideoCapture cam(1)
or
VideoCapture cam(any integer value)
which seems odd to me and hints in the same direction - that CV's VideoCapture does not work properly for me. A similar problem is described here but I also tried the code with a Sleep(1000) after opening the capture - without success.
EDIT: This is also working correctly now. I get my webcam with (0) and and error with (1) which is absolutely OK.

PDCurses KEY_ENTER does not work

Lets start with what my code looks like then I will explain my problem:
int main {
char ch; //Stores key presses
initscr();
raw();
nonl();
keypad(stdscr, TRUE);
noecho();
//Some code
ch = getch();
switch (ch) {
case KEY_UP:{
//Code that works
break;
}
case KEY_ENTER:{
//Some code- that doesn't work problem being the above
break;
}
//Other case statements
}
Now the problem:
The problem I run into if you haven't already worked it out is that when ever I press the enter/return key on my keyboard absolutely nothing happens.
I have tried changing the KEY_ENTER to '\n' - didn't work - even changed the char ch which when through multiple iterations including int and wchar_t.
All to no avail, and before you say search for answers and send me packing my bags to go onto a perilous adventure through every corner of the interwebs, I have already tried that, if I hadn't I wouldn't have ventured here, in search of aid.
So now my search has brought me here and I ask of you - the lovely people of the interwebs - to help me in my search of the answer I have been looking for
And to who ever may be valiant enough to answer it I give you my up most gratitude and thanks
Try case '\r':. (For good measure, you could do case '\r': case '\n': case KEY_ENTER:, as is basically done in testcurs.c, to capture all possibilities.) The call to nonl() is why you're getting '\r' instead of '\n'.
As for KEY_ENTER, my only excuse is that it's marked "not reliable" in the PDCurses comments. I could pretend that it's meant to represent the keypad's "Enter" key, rather than the key usually marked "Return" in the main part of the keyboard... except that PDCurses also has PADENTER, specifically for that purpose. In truth, like a lot of things in PDCurses, the reason KEY_ENTER is there, and defined the way it is, is a bit of a historical mess.

Platform-independent detection of arrow key press in C++

In a C++ console program, I've found how to detect and arrow key on Windows, and I've found a lot of other stuff that had nothing to do with the question (despite what I thought were good search terms), but I want to know if there is a platform-independent way to detect an arrow key press. A decent second place for this would be how to detect arrow key press in unix and mac. Code fragments would be appreciated.
There's no cross platform way to do it because it's not defined by either C or C++ standards (though there may be libraries which abstract away the differences when compiled on different platforms).
I believe the library you are looking for on POSIX boxes is curses, but I've never used it myself -- I could be wrong.
Keep in mind that it's entirely possible the console program (i.e. gnome-terminal or konsole or xterm) has monopolized the use of those keys for other functions.
As Billy said, there is no standard cross-platform way to do it.
Personally I use this (game-oriented) library for all inputs, cross-platform win/linux/mac : http://sourceforge.net/projects/wgois/
You can do this cross-platform by using SDL2.
Example code:
#include <SDL2/SDL.h>
int main()
{
SDL_Event event;
SDL_PollEvent(&event);
if(event.type == SDL_KEYDOWN)
{
// Move centerpoint of rotation for one of the trees:
switch(event.key.keysym.sym)
{
case SDLK_UP:
// do something
break;
case SDLK_DOWN:
// do something
break;
case SDLK_LEFT:
// do something
break;
case SDLK_RIGHT:
// do something
break;
case SDLK_ESCAPE:
// do something
return 0;
default:
break;
}
}
return 0;
}