I'm writing an live video processing program in c++, and want to be able to toggle three windows with the same mjpeg stream, in color, grayscale, and monochrome. I have all the image feeds running, but, since my screen is small, I want to be able to toggle them on and off individually. To do this, I have written the code below, but calling destroyWindow("[windowname]"); stops the whole program, instead. I've already read the documentation, and putting void in front of it doesn't help. Can anybody tell me what I'm doing wrong?
Here's the code (it's in an infinite loop, until the break you see below is called):
imshow("Color", imageColor);
imshow("Monochrome", imageMonochrome);
imshow("Grayscale", imageGrayscale);
int keyPressed = waitKey(0);
if (keyPressed > 0)
{
cout << keyPressed;
cout << "key was pressed\n";
// Press C to toggle color window
if (99 == keyPressed)
{
if (colorOpen)
{
cout << "Color window closed\n";
void destroyWindow("Color");
colorOpen = false;
}
if (!colorOpen)
{
cout << "Color window opened\n";
imshow("Color", imageColor);
colorOpen = true;
}
}
// Press M to toggle monochrome window
if (109 == keyPressed)
{
if (monochromeOpen)
{
cout << "Monochrome window closed\n";
void destroyWindow("Monochrome");
monochromeOpen = false;
}
if (!monochromeOpen)
{
cout << "Monochrome window opened\n";
imshow("Monochrome", imagebw);
monochromeOpen = true;
}
}
// Press G to toggle grayscale window
if (103 == keyPressed)
{
if (grayscaleOpen)
{
cout << "Grayscale window closed\n";
void destroyWindow("Grayscale");
grayscaleOpen = false;
}
if (!grayscaleOpen)
{
cout << "Grayscale window opened\n";
imshow("Grayscale", image);
grayscaleOpen = true;
}
}
// Break out of infinite loop when [ESC] is pressed:
if (27 == keyPressed)
{
cout << "Escape Pressed\n";
break;
}
}
The code you pasted terminates after calling destroyWindow (by running off the end of main). If that's not what you want to happen, write code that does something else after calling destroyWindow. Perhaps you want a loop?
Related
So i am making a software to help me with an arduino project, it is supossed to be like PUTTY. I programed the arduino to play different notes from Q-I(C4-C5) and the software is supossed to play thoes notes but i need to make it detect when the Key is pressed and released, how do i do that? I searched and found something but it is not working like it's supposed to here is the code:
int main(){
int KeyGet;
while(1)
{
KeyGet = getch();
if (GetKeyState(0x51) & 0x8000)
{
cout<<"key is pressed"<< endl;
}
else if(GetKeyState(0x51)& 0x0001)
{
cout<<"key is released"<< endl;
}
}
return 0;
The program just prints "key is pressed" when i press Q(0x51) and not "key released" as it should, insted it prints "key released" when i press something else other the Q. And i tried GetAsyncKeyState and tried
If (GetKeyState(0x51) != 0)
it still doesent work.
GetKeyState() requires a window and a message loop to keep the state machine updated. But you do not have a message loop. Also, getch() would swallow any key press+release anyway.
Also, GetKeyState(0x51) & 0x0001 is not the right way to detect a key release. That bit is meant for detecting the toggle state of togglable keys like CapsLock, etc.
In your example, you would need to get rid of getch() and use GetAsyncKeyState() instead, eg:
int main(){
bool down = false;
while (1) {
if (GetAsyncKeyState(0x51) < 0) {
if (!down) {
down = true;
cout << "key is pressed" << endl;
}
}
else {
if (down) {
down = false;
cout << "key is released"<< endl;
}
}
Sleep(0);
}
return 0;
}
Otherwise, you can use a WH_KEYBOARD[_LL] hook via SetWindowsHookEx() instead, so you can receive actual key down/up notifications in real-time.
I am stuck with the input with no enter input.
I tried to use kbhit() + getch() from conio.h and it doesn't work on my system (Win10 and Ubuntu - unistd.h and termios.h). Program just skips block with these functions.
Then I used GetAsynkKeyState from windows.h. It works in the game (Level) though buggy, but doesn't in a Menu. Program as well skips (or something) block with input dispatch.
Menu input:
// The menu interface
bool Menu::SelectLevel() {
cout << "Select the level:" << endl;
size_t arrow_pos = 0;
// Prints level's names and char to exit the game
for (size_t i = 0; i <= _levels.size(); ++i) {
// Draw arrow before selected level
if (i == arrow_pos) {
cout << '>' << i + 1 << " - " << _levels[i].first[0] << endl;;
}
// Draw arrow before the exit select
else if (i == _levels.size() && i == arrow_pos) {
cout << '>' << "Exit" << endl;
}
// Draw the exit option
else if (i == _levels.size()) {
cout << ' ' << "Exit" << arrow_pos << endl;
}
// Draw levels list
else {
cout << ' ' << i + 1 << " - " << _levels[i].first[0] << endl;
}
}
// Input from keyboard TODO DOESN'T WORK!:
// If 's' pressed move arrow down
PoollingDelay(1);
if (GetAsyncKeyState(0x53) & 0x8000) {
++arrow_pos;
// If arrow reached top it goes to the bottom
if (arrow_pos == _levels.size() + 1) {
arrow_pos = 0;
}
}
// If 'w' pressed move arrow up
else if (GetAsyncKeyState(0x57) & 0x8000) {
--arrow_pos;
// If arrow reached bottom it goes to the top
if (arrow_pos == 65535) {
arrow_pos = _levels.size() + 1;
}
}
// If Return pressed
else if (GetAsyncKeyState(VK_RETURN) & 0x8000) {
// Don't think it would be worthy
if (arrow_pos < 1 || arrow_pos > _levels.size() - 1) {
throw runtime_error("Wrong select: " + to_string(arrow_pos));
}
// If player tired of this shit
if (arrow_pos == _levels.size() - 1) {
ClearTerminal();
return false;
}
// Play
PlayLevel(arrow_pos);
}
ClearTerminal();
return true;
}
Level input:
// TO DO DOESN'T WORK!:
void Level::ReadCommand() {
PoollingDelay(100);
if (GetAsyncKeyState(0x57)) {
Move(_NORTH);
}
else if (GetAsyncKeyState(0x41)) {
Move(_WEST);
}
else if (GetAsyncKeyState(0x53)) {
Move(_SOUTH);
}
else if (GetAsyncKeyState(0x44)) {
Move(_EAST);
}
else if (GetAsyncKeyState(0x45)) {
throw runtime_error(exit_the_lvl);
}
}
Short answer: you can't using only C++ and its standard library.
This is because the language is not designed to handle low-level hardware events. To do this, you need to rely on a separate library, dedicated to handle I/O. Lots of them, some are more or less easy to integrate. For simple games, SDL is nice.
What is the difference between the output of event.window.windowID and SDL_GetWindowID()?
Why is it that std::cout << m_SDLEvent.window.windowID << std::endl;
outputs 1819558491 in console while std::cout << SDL_GetWindowID(m_SDLWindow) << std::endl; outputs 1 ?
How would I achieve getting the right ID of my SDL_Window* in the method below?
void InputManager::Update()
{
SDL_PollEvent(&m_SDLEvent);
switch (m_SDLEvent.type)
{
case SDL_QUIT:
std::cout << m_SDLEvent.window.windowID << std::endl;
SDL_HideWindow(SDL_GetWindowFromID(m_SDLEvent.window.windowID));
break;
}
}
You're seeing garbage window ID because you access an inactive union field. That's undefined behavior.
You can only access m_SDLEvent.window if m_SDLEvent.type == SDL_WINDOWEVENT.
But if m_SDLEvent.type == SDL_QUIT, you have to use m_SDLEvent.quit structure, which has no field for window id (because SDL_QUIT is not specific to a window, but means that the entire application should be closed).
Okay so HolyBlackCat's answer brought me to the right direction.
Instead of using SDL_QUIT (which is the quit event for the entire app, not one window) I should've checked for SDL_WINDOWEVENT_CLOSE which is an SDL_WINDOWEVENT which can be received by m_SDLEvent.window.event instead of m_SDLEvent.type
So the code now looks like this:
void InputManager::Update()
{
SDL_PollEvent(&m_SDLEvent);
if (m_SDLEvent.type == SDL_WINDOWEVENT)
{
switch (m_SDLEvent.window.event)
{
case SDL_WINDOWEVENT_CLOSE:
std::cout << m_SDLEvent.window.windowID << std::endl;
SDL_HideWindow(SDL_GetWindowFromID(m_SDLEvent.window.windowID));
break;
}
}
}
Now std::cout << m_SDLEvent.window.windowID << std::endl; outputs the correct ID.
I am making console style game in sfml. It's graphical interface but game itself contains console. I'm using Text Entered event for writing things in console but i also want to move the cursor (console cursor not mouse) with arrow keys. To be more specific in text entered event i am using event.text.unicode for key value. But arrow keys unicode values not working in my pc. I used 37 for left arrow, 39 for right arrow but it doesn't work. This is my console's key process function.
void Console::update(int unicode) {
if(unicode == 8) { // Backspace
deleteLast();
} else if(unicode == 13) { // Enter
newLine();
} else if(unicode == 37) { // Left arrow key
currentX--;
std::cout << "Left arrow" << std::endl;
} else if(unicode == 39) { // Right arrow key
currentX++;
std::cout << "Right arrow" << std::endl;
} else { // Normal characters
buffer[(currentY == 0) ? currentX : (currentY * maxColumn) + currentX] = (char)unicode;
currentX++;
if(currentX == maxColumn - 1) {
newLine();
}
std::cout << "[KEY TYPED] X: " << currentX << " Y: " << currentY << std::endl;
}
}
Thanks in advance :)
Edit: I think i solved. I used KeyPressed event for handling special keys. And TextEntered for handling normal characters.
For those having the same problem:
From an Event type variable, first check if its a keyboard event
if(event.type == sf::Event::KeyPressed)
Then check if its an arrow:
if(event.key.code == sf::Keyboard::Up)
//do stuff
if(event.key.code == sf::Keyboard::Down)
//do stuff
I have a simple OpenCV application that takes a video stream from the webcam, and when the spacebar is pressed it captures the current image and freezes on that image. When I try to use the cv::imwrite() method to save the picture to disk, it does not work. The code successfully compiles but it does not save the image. It is returning a false value as well from the call. I am not sure if this is an issue of type of image or something else, but I seem to be stumped.
Here is the code for my current cpp class:
#include <iostream>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace std;
using namespace cv;
Mat picture;
char key;
class FacialRec {
};
int main() {
//Starting the video
VideoCapture videoCapture(0);
if (!videoCapture.isOpened()) {
cout << "Unable to open video file." << endl;
return 1;
}
namedWindow("Webcam", CV_WINDOW_AUTOSIZE);
while(true) {
Mat frame;
videoCapture.retrieve(frame);
bool success = videoCapture.read(frame);
if (!success) {
cout << "Could not read from video file" << endl;
return 1;
}
imshow("Webcam", frame);
key = waitKey(30);
if (key == 27) { //escape key pressed: stop program
cout << "ESC pressed. Program closing..." << endl;
break;
}else if (key == ' ') { //spacebar pressed: take a picture
picture = frame;
key = -1;
while (true) {
imshow("Webcam", picture);
key = waitKey(30);
if (key == 27 || key == 32) {
cout << "ESC or SPACE pressed. Returning to video..." << endl;
break;
}
if (key == 115) {
//trying to save to current directory
bool maybe = imwrite("/testimage.jpg", picture);
// maybe bool is always getting value of 0, or false
cout << "s was pressed. saving image " << maybe << endl;
}
}
}
}
return 0;
}
You are attempting to write testimage.jpg to the / directory. The executing program probably doesn't have sufficient permissions to write to that directory. Based on your comment, you probably want
//trying to save to current directory
bool maybe = imwrite("./testimage.jpg", picture);
Since . denotes the current working directory.
OpenCV sometimes has problems to write to a .jpg image. Try to change that to .png or .bmp to see if that makes a difference in your case.
If you have further issues with writing images, you can debug them in OpenCV by adding this few lines of code to display them and see if they are valid:
// Create a window for display.
namedWindow( "Display window", WINDOW_AUTOSIZE );
// Show our image inside it.
imshow( "Display window", picture );
// Wait for a keystroke in the window
waitKey(0);
A few suggestions.
try a different file format.
does your IDE defiantly know your target folder / home path directory?
Is your image definitely valid? does it show when you imshow()?