How to compile C++ code that contains OpenCV library without Makefile? - c++

I just started learning OpenCV with C++. I built OpenCV from source on Linux machine. I use Visual Studio Code text editor. I want to compile C++ code that contains OpenCV library without Makefile. I added /usr/local/opencv4/** to includePath variable. But it didn't work. I'm receiving opencv2/opencv.hpp error. Is it possible build C++ code that contains OpenCV includes without Makefile? How can I do it?
My Code
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat image = imread("Enter the Address"
"of Input Image",
IMREAD_GRAYSCALE);
if (image.empty()) {
cout << "Image File "
<< "Not Found" << endl;
cin.get();
return -1;
}
imshow("Window Name", image);
waitKey(0);
return 0;
}

You will have to tell the compiler the location of the header files and library files. As mentioned by kotatsuyaki you can use pkg-config to do this for your.
Example with gcc and pkg-config:
g++ *.cpp -o program_name `pkg-config --cflags --libs opencv4`
Example with gcc and without pkg-config:
g++ *.cpp -o program_name -I/PATH/TO/OPENCV/INCLUDE/FOLDER -L/PATH/TO/OPENCV/LIB/FOLDER -lopencv_something -lopencv_somethingelse ... etc
In Windows with cl you can do the same as the g++ without pkg-config:
cl main.cpp /I"PATH TO OPENCV ICNLUDE FOLDER" /link /LIBPATH:"PATH TO OPENCV LIB FOLDER" opencv_library1.lib opencv_libarary2.lib ... etc.

Related

SDL returns no output when I try to print statements using cout

I installed the MinGW version of SDL from their website.
I created a sample piece of code just to test if I could include the library without any errors.
#include <iostream>
#include <SDL.h>
using namespace std;
int main(int argc, char* argv[]) {
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
cout << "SDL INIT FAILED" << endl;
return 1;
}
cout << "SDL INIT SUCCEEDED" << endl;
SDL_Quit();
return 0;
}
I also created a Makefile:
#OBJS specifies which files to compile as part of the project
OBJS = main.cpp
#CC specifies which compiler we're using
CC = g++
#INCLUDE_PATHS specifies the additional include paths we'll need
INCLUDE_PATHS = -Isrc\includes
#LIBRARY_PATHS specifies the additional library paths we'll need
LIBRARY_PATHS = -Lsrc\lib
#COMPILER_FLAGS specifies the additional compilation options we're using
# -w suppresses all warnings
# -Wl,-subsystem,windows gets rid of the console window
COMPILER_FLAGS = -w -Wl,-subsystem,windows
#LINKER_FLAGS specifies the libraries we're linking against
LINKER_FLAGS = -lmingw32 -lSDL2main -lSDL2
#OBJ_NAME specifies the name of our exectuable
OBJ_NAME = main
#This is the target that compiles our executable
all : $(OBJS)
$(CC) $(OBJS) $(INCLUDE_PATHS) $(LIBRARY_PATHS) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OBJ_NAME)
If I don't include the int argc, char* argv[] inside of int main() and try to ming32-make, it throws an error:
C:\Users\username\Documents\Projects\C++\SDL_test> mingw32-make
g++ main.cpp -Isrc\includes -Lsrc\lib -w -Wl,-subsystem,windows -lmingw32 -lSDL2main -lSDL2 -o main
c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: src\lib/libSDL2main.a(SDL_windows_main.o): in function `main_getcmdline':
/Users/valve/release/SDL2/SDL2-2.26.2-source/foo-x64/../src/main/windows/SDL_windows_main.c:82: undefined reference to `SDL_main'
collect2.exe: error: ld returned 1 exit status
mingw32-make: *** [Makefile:26: all] Error 1
When I include int argc, char* argv[], it doesn't give any errors but doesn't print anything either.
C:\Users\username\Documents\Projects\C++\SDL_test> mingw32-make
g++ main.cpp -Isrc\includes -Lsrc\lib -w -Wl,-subsystem,windows -lmingw32 -lSDL2main -lSDL2 -o main
C:\Users\username\Documents\Projects\C++\SDL_test>
When I use make instead of mingw32-make, the output remains the same.
I am using VSCode and I have included the header files and lib files in an src folder in the same directory as my script and also moved the SDL2.dll file in the root folder:
My C++ Configuration on VSCode:
Compiler Path: C:\MinGW\bin\g++.exe
Compiler Arguments:
IntelliSense mode: gcc-x64 (legacy) // Because using anything else says the the mode is incompatible with the compiler path.
Include path:
${workspaceFolder}/**
${workspaceFolder}/src/includes
I had also recieved SDL.h: file or directory not found errors before this and I fixed them by creating the Makefile.
Is there something I'm missing? Does SDL not output to stdout, because I've seen tutorials online and they are able to get outputs from cout fine on them.
I am expecting cout to work when I run the script.
-Wl,-subsystem,windows (aka -mwindows) hides the console window, and with it all output. Remove it, and use it only in the release builds.
-w suppresses all warnings
This is extremely unwise. Prefer -Wall -Wextra -Wdeprecated to enable most common warnings, plus -std=c++20 -pedantic-errors to enforce standard compliance (replace 20 with the latest version supported by your compiler).
As suggested by #keltar, you might be able to get output even from a program built with -mwindows if you redirect it to a file, using my_program.exe >output.txt.
EDIT: The issue was that I hadn't installed SDL2 the right way. I installed MSYS2 and used it to install MinGW-w64.
I then used the Msys2 command-line interface to install SDL2 using these commands:
pacman -Syu
pacman -Su
pacman -S mingw-w64-x86_64-SDL2
This installed the header and lib files for SDL in their proper locations. I was then able to include those files in my code.
I changed the main function from int main(int argc, char* argv[]) to int WinMain(int argc, char* argv[]) because I'm on Windows and this helps get rid of the undefined reference to WinMain error.
My working code:
#include <iostream>
#include <SDL2/SDL.h>
using namespace std;
int WinMain(int argc, char* argv[]) {
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
cout << "SDL INIT FAILED" << endl;
return 1;
}
cout << "SDL INIT SUCCESSFUL" << endl;
}

Compiling OpenCV Based Script With G++

I want to begin writing saying that I know that this topic has been talked about multiple times. I can see several posts with similar titles as I'm typing this now. The reason that I'm asking this question once again is because I've tried what those posts stay, and it still won't work. I've copied a simple script that upscales an image using opencv in C++ to begin the learning journey and to make a script that I hope to use in the future very often, maybe even share on GitHub. With that being said, here's more detail about my issue.
In my IDE, Visual Studio Code, my include path has been set to "/opt/homebrew/Cellar/opencv/4.6.0/include/opencv4/".
I've tried using the -I arguments, -l arguments, whatever this is: "pkg-config --cflags --libs opencv4", but none of that worked.
The only time that I could get it to work is using the following command, but even then, g++ returned: fatal error: too many errors emitted, stopping now [-ferror-limit=] 41 warnings and 20 errors generated.
Here's the program that I have:
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main() {
Mat frame = imread("/Users/karsoneskind/Desktop/Programming/C++/ibootimformer/tests/image.jpg");
namedWindow("Output", 0);
namedWindow("Input", 0);
Mat output;
resize(frame, output, Size(1000, 200), 0, 0);
imshow("Output", output);
imshow("Input", frame);
waitKey(0);
}
Edit: This is the command in terminal I used to try to compile the code:
g++ test.cpp -o test pkg-config --cflags --libs opencv4

Undefined reference to cv::Mat::Mat()

I made a simple c++ code that reads the webcam image and display it. However, when I compile, I get the error - 'Undefined reference to cv::Mat::Mat()'. I don't know why it shows two Mat's. Here is my code:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include <stdlib.h>
int main() {
cv::VideoCapture cap(0);
if (!cap.isOpened){
std::cout << "Error opening camera" << std::endl;
}
cv::Mat img;
while(1){
cap >> img;
cv::imshow("output", img);
cv::waitKey(1);
}
}
This is how I compile it
g++ example.cpp `pkg-config --libs opencv4`
I can't figure out why the error shows up. Any help is appreciated!
This works on my Linux:
g++ main.cpp -I/usr/include/opencv4/ -lopencv_core -lopencv_videoio -lopencv_highgui
While this is not portable, (using cmake would do the trick, but you'd need to learn cmake first), I'll give you a hint how you can discover this yourself.
Whenever you see an error like Undefined reference to cv::Mat::Mat(), go to the documentation at https://docs.opencv.org/ , chose the newest version (here: https://docs.opencv.org/4.5.5/ ), enter, in the "search" window, the name of a class/function the linker cannot find (here: Mat), read the header that defines it (here: #include<opencv2/core/mat.hpp>), then the missing library will have the name libopencv_core.* or libopencv_mat.*. Find whichever is in your machine (e.g. inside /user/lib) and link it, omitting the extension and the beginning lib in the name. In my case the library location, with the full path, is /usr/lib/libopencv_core.so, so I link it with -lopencv_core. Then you need to find the remaining libs in the same way.
Learn how to automatize this, e.g. via a Makefile, CMakeLists.txt or just a simple bash script.

Including external libraries in CodeRunner 2 app?

I've always used Xcode to compile OpenCV based code in c++. The procedure in Xcode was quite simple, I just had to mention the paths and add the necessary lib files to the project. Theres this app called CodeRunner 2 for macOS. Theres no proper documentation on how to include external libraries to compile code in this app. Is it possible to link OpenCV headers and compile them in CodeRunner ? If yes, could someone post the steps?
You can run OpenCV in CodeRunner by setting up a new language. Go to Preferences -> Languages, right-click C++, and select Duplicate. Name the new language "C++ OpenCV". On the right side of the preferences window, click Settings then the Edit Script button. Look for this line (or something similar):
xcrun clang++ -x c++ -lc++ -o "$out" "${files[#]}" "${#:1}"
Add the clang++ command line parameters for OpenCV after "$out". Here's my version:
xcrun clang++ -x c++ -lc++ -o "$out" -I/usr/local/opt/opencv3/include -L/usr/local/opt/opencv3/lib -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs -lopencv_videoio -lopencv_calib3d "${files[#]}" "${#:1}"
Modify the -I and -L parameters to match your OpenCV install path. On this machine I used Homebrew to install OpenCV so it was installed in /usr/local/opt. On other machines I've compiled from source so OpenCV is installed in /usr/local/lib.
Modify the -l parameters to include the libraries you typically use.
After saving the compile script, go back to Preferences -> Languages and select the Templates button. You can set up a template for OpenCV programs. Here's mine:
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
int main(int argc, char *argv[]) {
cv::Mat image;
// read an image
if (argc < 2)
image = cv::imread("img.jpg");
else
image = cv::imread(argv[1]);
if (!image.data) {
std::cout << "Image file not found\n";
return 1;
}
// create image window named "asdfasdf"
cv::namedWindow("asdfasdf");
// show the image on window
cv::imshow("asdfasdf", image);
// wait for key
cv::waitKey(0);
return 0;
}
The previous reply by SSteve is great and also helps me sort out linking Boost library in CodeRunner.
Because the solution in the previous reply is specific to OpenCV library, a carelessly adding to the clang++ command line for external libraries in general might just generate massive building errors, which was the case when I tried to link Boost library.
Here, I want to clarify the unclear bit in SSteve's reply so everyone knows how and where to modify the command line before compiling their code with external library in Mac OS system.
I will use my case to explain, but in some point I will inform you of the tricky bits in CodeRunner setting or general command line typing.
I use macport to install the Boost library by
sudo port install boost
header file is located at /opt/local/include
library is located at /opt/local/lib/
If you cannot find the specific sub-library in Boost, open your terminal and type
cd /opt/local/lib/
find . -iname "*boost*"
and you should see all sub-libraries of Boost ( static library ends with .a and dynamic library ends with .dylib ) as below.
Before you start to modify the original command line ( supporting c++ 14 version ) such as
xcrun clang++ -x c++ -std=c++14 -stdlib=libc++ -lc++ -o "$out" "${files[#]}" "${#:1}" ${CR_DEBUGGING:+-g}
you need to know the directory of header file is after -I and the directory of Boost library is after -L, like
-I /opt/local/include/
-L /opt/local/lib/
In order to use a compiled static or dynamic sub-library in Boost ( see figure above ), you have to include it specifically after -L /opt/local/lib/. However, simply copying the library name without file extension either .a or .dylib would never let CodeRunner find the library you expect to run !!!
The detail is explained here and I just quota the important bit below
clang -dynamiclib -o libtest.dylib file1.o file2.o -L/some/library/path -lname_of_library_without_lib_prefix
To run such an example code in Boost Quickstart Document
#include <boost/regex.hpp>
#include <iostream>
#include <string>
int main()
{
std::string line;
boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );
while (std::cin)
{
std::getline(std::cin, line);
boost::smatch matches;
if (boost::regex_match(line, matches, pat))
std::cout << matches[2] << std::endl;
}
}
the way to include <boost/regex.hpp> now is by
xcrun clang++ -x c++ -std=c++14 -stdlib=libc++ -lc++ -o "$out" -I /opt/local/include/ -L /opt/local/lib -lboost_regex-mt "${files[#]}" "${#:1}" ${CR_DEBUGGING:+-g}
By using this command line, you should be able to compile the example code with Boost library.
Just remember to replace the prefix -lib with -l and exclude the file extension in the command line.
At last, there are some alternative solution to include the external library by using Xcode, which is in here

Compiling C++ code with allegro 5 and g++

What flags do I need to add to g++ in order to compile code using allegro 5? I tried
g++ allegro5test.cpp -o allegro5test `allegro-config --libs`
but that is not working. I'm using ubuntu 11.04. I installed allegro 5 using the instructions at http://wiki.allegro.cc/index.php?title=Install_Allegro5_From_SVN/Linux/Debian
I tried:
g++ allegro5test.cpp -o allegro5test `allegro-config --cflags --libs`
And it also gives a bunch of undefined errors, like: undefined reference to `al_install_system'
allegro-config --cflags --libs outputs:
-I/usr/local/include
-L/usr/local/lib -lalleg
So you successfully installed allegro5 on your system from the SVN. One thing you should know is that this build doesn't come with allegro-config. If you have it on your system it means you have previously installed allegro4.
allegro5 brings many changes, including different initialization procedures, library and function names.
Here's a hello world application for new version:
#include <stdio.h>
#include <allegro5/allegro.h>
int main(int argc, char **argv)
{
ALLEGRO_DISPLAY *display = NULL;
if(!al_init()) {
fprintf(stderr, "failed to initialize allegro!\n");
return -1;
}
display = al_create_display(640, 480);
if(!display) {
fprintf(stderr, "failed to create display!\n");
return -1;
}
al_clear_to_color(al_map_rgb(0,0,0));
al_flip_display();
al_rest(10.0);
al_destroy_display(display);
return 0;
}
Notice how the command to compile this application refers to another include directory and library names, which are different from the previous version of allegro:
g++ hello.cpp -o hello -I/usr/include/allegro5 -L/usr/lib -lallegro
Allegro 5 uses pkg-config.
pkg-config --libs allegro-5.0 allegro_image-5.0
And so on for each library you are using.