Combine multiple images and display it in Qt - c++

I am a beginner in OpenCV and Qt, my project now is combining multiple images and display it on Qt Creator.
#include <stdio.h>
#include <iostream>
#include <mutex>
#include <opencv2/opencv.hpp>
using namespace std;
int main(int argc, char** argv) {
string img_path = "/home/m/pictures/cat.jpg";
std::vector<cv::Mat> img_pool;
for (int i=0;i<10;i++)
{
cv::Mat data = cv::imread(img_path,-1);
img_pool.push_back(data);
}
cv::Mat data = cv::imread(img_path,-1);
cv::namedWindow("image", CV_WINDOW_NORMAL);
cv::imshow("image",data);
cv::waitKey(0);
cv::Mat data_dst = cv::Mat::zeros(500, 500, data.type());
cv::Mat data_resize;
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
cv::resize( img_pool[3], data_resize, cv::Size(50,50));
cv::Rect f_target(i*50,j*50,50,50);
data_resize.copyTo(data_dst(f_target));
}
}
cv::namedWindow("image_n", CV_WINDOW_NORMAL);
cv::imshow("image_n",data_dst);
cv::waitKey(0);
return 0;
}
Here is the result:
My code now can display one image but what I want to do is display different multiple images, I think I need to load the images or image path to the vector but I failed, so someone can help me?

There is no Qt used in your code. If you want something like this with Qt, you can use a simple widget with a grid layout or a flowlayout. Then load all the images from a path in an array of QImage and the display it.
You can find an example with FlowLayout here. You can use a QLabel to display the image, convert your QImage to QPixmap and the use:
QImage yourImage("path");
QLabel image new QLabel(centralwidget);
imagelabel->setGeometry(QRect(20, 10, 371, 311));
imagelabel->setPixmap(QPixmap(QPixmap::fromImage(yourImage));
If you are new with Qt, you can integrate it easily with QML using a FlowLayout and and array of QML components. Look this example of the usage of an ImageViewer

Related

Overlay using opencv using C++

My question is about trying to fixing the italized line so that my overlay will work properly and instead of black pixels there are white pixels based on my conditional statement. I have tried several things such as using different types such as:
out1.at<Vec3b>(i,j)[0]=image.at<Vec3b>(i,j)[0];
out1.at<Vec3b>(i,j)[1]=image.at<Vec3b>(i,j)[1];
out1.at<Vec3b>(i,j)[2]=image.at<Vec3b>(i,j)[2];
But I got a heap error. I believe I am really close but I need some advice or guidance. Please excuse any errors that I have made posting for this is my first post.
Here is my code.
#include <iostream>
#include <stdint.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
using namespace std;
using namespace cv;
int main(int argv, char** argc)
{
Mat image; // new blank image
Mat image2;
Mat out1;
image2 = cv::imread("test2.bmp",CV_LOAD_IMAGE_GRAYSCALE); // read the file
image = cv::imread("test1.bmp",CV_LOAD_IMAGE_GRAYSCALE);
if (!image.data) // error handling if file does not load
{
cout<< "Image 1 not loaded";
return -1;
}
if (!image2.data)
{
cout << "Image 2 not loaded";
return -1;
}
// resize images to make sure all images is the same size
cv::resize(image2, image2, image.size());
cv::resize(image2, out1, image.size());
// copying content of overlay image to output file
//image2.copyTo(out1);
out1 = image2.clone();
// for loop comparing pixels to original image
for (int i =0; i < out1.rows; i++)
{
for(int j =0; j < out1.cols; j++)
{
//Vec3b color = image.at<Vec3b>(Point(i,j));
if(out1.at<uchar>(i,j)==0 && out1.at<uchar>(i,j) ==0 &&
out1.at<uchar>(i,j)==0)
{
out1.at<Vec3b>(i,j)[0]=255; // blue channel
out1.at<Vec3b>(i,j)[1]=255; // green channel
out1.at<Vec3b>(i,j)[2]=255; // red channel
}
else
*out1.at<uchar>(i,j) = image.at<uchar>(i,j);*
}
}
cv::imwrite("out1.bmp",out1); // save to output file
namedWindow("Display window", CV_WINDOW_AUTOSIZE);// creat a window to
display w/label
imshow("Display window",out1); // show image inside display window
waitKey(0);
return 0;
}
My image is close to being overlayed correctly. My issue is that the
pixels shows up black instead of white due to a certain line in my
program

Unable to detect ArUco markers with OpenCV 3.1.0

I am trying to code a simple C++ routine to first write a predefined dictionary of ArUco markers (e.g. 4x4_100) to a folder and then detect ArUco markers in a specific image selected from the folder using OpenCV 3.1 and Visual Studio 2017. I have compiled all the OpenCV-contrib libraries required to use ArUco markers. My routine builds without any error, but I am having trouble detecting the markers even after supplying all the correct arguments (e.g. image, Dictionary, etc.) to the in-built "aruco::detectMarkers" function. Could you please help me understand what`s wrong with my approach? Below is a minimal working example and the test image is attached here "4x4Marker_40.jpg":
#include "opencv2\core.hpp"
#include "opencv2\imgproc.hpp"
#include "opencv2\imgcodecs.hpp"
#include "opencv2\aruco.hpp"
#include "opencv2\highgui.hpp"
#include <sstream>
#include <fstream>
#include <iostream>
using namespace cv;
using namespace std;
// Function to write ArUco markers
void createArucoMarkers()
{
// Define variable to store the output markers
Mat outputMarker;
// Choose a predefined Dictionary of markers
Ptr< aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Write each of the markers to a '.jpg' image file
for (int i = 0; i < 50; i++)
{
aruco::drawMarker(markerDictionary, i, 500, outputMarker, 1);
ostringstream convert;
string imageName = "4x4Marker_";
convert << imageName << i << ".jpg";
imwrite(convert.str(), outputMarker);
}
}
// Main body of the routine
int main(int argv, char** argc)
{
createArucoMarkers();
// Read a specific image
Mat frame = imread("4x4Marker_40.jpg", CV_LOAD_IMAGE_UNCHANGED);
// Define variables to store the output of marker detection
vector<int> markerIds;
vector<vector<Point2f>> markerCorners, rejectedCandidates;
// Define a Dictionary type variable for marker detection
Ptr<aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Detect markers
aruco::detectMarkers(frame, markerDictionary, markerCorners, markerIds);
// Display the image
namedWindow("Webcam", CV_WINDOW_AUTOSIZE);
imshow("Webcam", frame);
// Draw detected markers on the displayed image
aruco::drawDetectedMarkers(frame, markerCorners, markerIds);
cout << "\nmarker ID is:\t"<<markerIds.size();
waitKey();
}
There are a few problems in your code:
You are displaying the image with imshow before calling drawDetectedMarkers so you'll never see the detected marker.
You are displaying the size of the markerIds vector instead of the value contained within it.
(This is the main problem) Your marker has no white space around it so it's impossible to detect.
One suggestion: use forward slashes, not backslashes in your #include statements. Forward slashes work everywhere, backslashes only work on Windows.
This worked on my machine. Note that I loaded the image as a color image to make it easier to see the results of drawDetectedMarkers.
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/highgui.hpp>
#include <sstream>
#include <fstream>
#include <iostream>
using namespace cv;
using namespace std;
// Function to write ArUco markers
void createArucoMarkers()
{
// Create image to hold the marker plus surrounding white space
Mat outputImage(700, 700, CV_8UC1);
// Fill the image with white
outputImage = Scalar(255);
// Define an ROI to write the marker into
Rect markerRect(100, 100, 500, 500);
Mat outputMarker(outputImage, markerRect);
// Choose a predefined Dictionary of markers
Ptr< aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Write each of the markers to a '.jpg' image file
for (int i = 0; i < 50; i++)
{
//Draw the marker into the ROI
aruco::drawMarker(markerDictionary, i, 500, outputMarker, 1);
ostringstream convert;
string imageName = "4x4Marker_";
convert << imageName << i << ".jpg";
// Note we are writing outputImage, not outputMarker
imwrite(convert.str(), outputImage);
}
}
// Main body of the routine
int main(int argv, char** argc)
{
createArucoMarkers();
// Read a specific image
Mat frame = imread("4x4Marker_40.jpg", CV_LOAD_IMAGE_COLOR);
// Define variables to store the output of marker detection
vector<int> markerIds;
vector<vector<Point2f>> markerCorners, rejectedCandidates;
// Define a Dictionary type variable for marker detection
Ptr<aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Detect markers
aruco::detectMarkers(frame, markerDictionary, markerCorners, markerIds);
// Display the image
namedWindow("Webcam", CV_WINDOW_AUTOSIZE);
// Draw detected markers on the displayed image
aruco::drawDetectedMarkers(frame, markerCorners, markerIds);
// Show the image with the detected marker
imshow("Webcam", frame);
// If a marker was identified, show its ID
if (markerIds.size() > 0) {
cout << "\nmarker ID is:\t" << markerIds[0] << endl;
}
waitKey(0);
}

loop and display through a vector of images

I am using opencv and c++. I am doing a very simple program. What is does is it takes 3 images in a vector mat,convert those images to hsv and again stores the hsv's of the original image in a vector. I want to display all the 3 hsv images obtained. But when my program loops, it displays only the last hsv image in the vector. Here is my code: http://pastebin.com/z7FBrtxs.
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(){
vector<Mat> imgs;
Mat left=imread("left.jpg");
Mat front=imread("front.jpg");
Mat right=imread("right.jpg");
imgs.push_back(left);
imgs.push_back(front);
imgs.push_back(right);
vector<Mat> hsvs;
Mat left_hsv;
Mat front_hsv;
Mat right_hsv;
cvtColor(left,left_hsv,CV_BGR2HSV);
cvtColor(front,front_hsv,CV_BGR2HSV);
cvtColor(right,right_hsv,CV_BGR2HSV);
hsvs.push_back(left_hsv);
hsvs.push_back(front_hsv);
hsvs.push_back(right_hsv);
for(int i=0;i<3;i++){
imshow("hsv",hsvs[i]);
}
waitKey(0);
return 0;
}
This
for(int i=0;i<3;i++){
imshow("hsv",hsvs[i]);
}
waitKey(0);
means that you are displaying all images in the window named "hsv". And after displaying the last one, you wait for user input. Thus, the images are actually all showed in the window, in sequence, it's just that they switch so fast you never see it.
Change it to
for(int i=0;i<3;i++){
imshow("hsv",hsvs[i]);
waitKey(0);
}
and you should be good.
This change means each image will be shown in the "hsv" window, and then wait for you to push a button before showing the next image.
You could also show multiple windows at once by just renaming the windows to "hsv1", "hsv2", etc.
Either use:
for(int i=0;i<3;i++){
imshow("hsv",hsvs[i]);
waitKey(0); //Note: wait for user input for every image
}
or show them in three different named windows (see documentation).
As there are no coordinates provided, I guess all images are drawn in the same default place (a viewport origin), and the last image was painted over all previous ones.

c++ image processing tutorials withuot 3rd party library

I want to learn image processing in C++, but I don't want to use any 3rd party library for image manipulation. Use of library for displaying the image(s) is okay, but all manipulations are to be done manually.
Please point me to some good tutorials. I'm a beginner in this field, so I also need to know how to display an image.
Seems you lack basic knowledge of Digital Image Processing, I recommand to you this book.
Digital Image Processing (3rd Edition) Rafael C.Gonzalez / Richard E.Woods http://www.amazon.com/dp/013168728X
For basic operation using OpenCV(which I am familiar with), here is an example:
/*
function:image reverse
*/
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
int main(int argc, char *argv[])
{
IplImage* img = 0;
int height,width,step,channels;
uchar *data;
int i,j,k;
if(argc<2)
{
printf("Usage: main <image-file-name>/n/7");
exit(0);
}
// Load image
img=cvLoadImage(argv[1],-1);
if(!img)
{
printf("Could not load image file: %s\n",argv[1]);
exit(0);
}
// acquire image info
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
data = (uchar *)img->imageData;
printf("Processing a %dx%d image with %d channels/n",height,width,channels);
// create display window
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin", 100, 100);
// reverse image
for(i=0;i<height;i++)
for(j=0;j<width;j++)
for(k=0;k<channels;k++)
data[i*step+j*channels+k]=255-data[i*step+j*channels+k];
// display reversed image
cvShowImage("mainWin", img );
cvWaitKey(0);
cvReleaseImage(&img );
printf("height=%d width=%d step=%d channels=%d",height,width,step,channels);
return 0;
}
Try CImg (it's entirely self-contained) - http://cimg.sourceforge.net/

watershed segmentation opencv xcode

I am now learning a code from the opencv codebook (OpenCV 2 Computer Vision Application Programming Cookbook): Chapter 5, Segmenting images using watersheds, page 131.
Here is my main code:
#include "opencv2/opencv.hpp"
#include <string>
using namespace cv;
using namespace std;
class WatershedSegmenter {
private:
cv::Mat markers;
public:
void setMarkers(const cv::Mat& markerImage){
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(const cv::Mat &image){
cv::watershed(image,markers);
return markers;
}
};
int main ()
{
cv::Mat image = cv::imread("/Users/yaozhongsong/Pictures/IMG_1648.JPG");
// Eliminate noise and smaller objects
cv::Mat fg;
cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),6);
// Identify image pixels without objects
cv::Mat bg;
cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),6);
cv::threshold(bg,bg,1,128,cv::THRESH_BINARY_INV);
// Create markers image
cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));
markers= fg+bg;
// Create watershed segmentation object
WatershedSegmenter segmenter;
// Set markers and process
segmenter.setMarkers(markers);
segmenter.process(image);
imshow("a",image);
std::cout<<".";
cv::waitKey(0);
}
However, it doesn't work. How could I initialize a binary image? And how could I make this segmentation code work?
I am not very clear about this part of the book.
Thanks in advance!
There's a couple of things that should be mentioned about your code:
Watershed expects the input and the output image to have the same size;
You probably want to get rid of the const parameters in the methods;
Notice that the result of watershed is actually markers and not image as your code suggests; About that, you need to grab the return of process()!
This is your code, with the fixes above:
// Usage: ./app input.jpg
#include "opencv2/opencv.hpp"
#include <string>
using namespace cv;
using namespace std;
class WatershedSegmenter{
private:
cv::Mat markers;
public:
void setMarkers(cv::Mat& markerImage)
{
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(cv::Mat &image)
{
cv::watershed(image, markers);
markers.convertTo(markers,CV_8U);
return markers;
}
};
int main(int argc, char* argv[])
{
cv::Mat image = cv::imread(argv[1]);
cv::Mat binary;// = cv::imread(argv[2], 0);
cv::cvtColor(image, binary, CV_BGR2GRAY);
cv::threshold(binary, binary, 100, 255, THRESH_BINARY);
imshow("originalimage", image);
imshow("originalbinary", binary);
// Eliminate noise and smaller objects
cv::Mat fg;
cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),2);
imshow("fg", fg);
// Identify image pixels without objects
cv::Mat bg;
cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),3);
cv::threshold(bg,bg,1, 128,cv::THRESH_BINARY_INV);
imshow("bg", bg);
// Create markers image
cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));
markers= fg+bg;
imshow("markers", markers);
// Create watershed segmentation object
WatershedSegmenter segmenter;
segmenter.setMarkers(markers);
cv::Mat result = segmenter.process(image);
result.convertTo(result,CV_8U);
imshow("final_result", result);
cv::waitKey(0);
return 0;
}
I took the liberty of using Abid's input image for testing and this is what I got:
Below is the simplified version of your code, and it works fine for me. Check it out :
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main ()
{
Mat image = imread("sofwatershed.jpg");
Mat binary = imread("sofwsthresh.png",0);
// Eliminate noise and smaller objects
Mat fg;
erode(binary,fg,Mat(),Point(-1,-1),2);
// Identify image pixels without objects
Mat bg;
dilate(binary,bg,Mat(),Point(-1,-1),3);
threshold(bg,bg,1,128,THRESH_BINARY_INV);
// Create markers image
Mat markers(binary.size(),CV_8U,Scalar(0));
markers= fg+bg;
markers.convertTo(markers, CV_32S);
watershed(image,markers);
markers.convertTo(markers,CV_8U);
imshow("a",markers);
waitKey(0);
}
Below is my input image :
Below is my output image :
See the code explanation here : Simple watershed Sample in OpenCV
I had the same problem as you, following the exact same code sample of the cookbook (great book btw).
Just to place the matter I was coding under Visual Studio 2013 and OpenCV 2.4.8. After a lot of searching and no solutions I decided to change the IDE.
It's still Visual Studio BUT it's 2010!!!! And boom it works!
Becareful of how you configure Visual Studio with OpenCV. Here's a great tutorial for installation here
Good day to all