Overlay using opencv using C++ - 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

Related

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);
}

Why Png Compression doesn't change destination size (C++)? OpenCV VS2010

I have tested this code with various values from compression_params.push_back(1); to compression_params.push_back(9); but the PNG image always has same size. 1950x1080 (contains screenshot of Google map - not the satellite photo) has 2,36 MB (2 477 230 bytes. Is this normal is takes so much. I thought png images are small size if they do not contain photos.
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(1);
try {
imwrite("RGB_1.png", source, compression_params);
}
catch (runtime_error& ex) {
fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what());
return 1;
}
Why is it? Also I cannot find out how to create the PNG object in memory (to keep the encode data in buffer). This means, I would like to save more images into one file (e.g database) so I need to convert into buffer and then save add buffer to file. Is it possible to do it usin OpenCV? Your tips welcome.
I think PNG should support some feature where the algorithm auto-selects background color, so if you see some cv::Scallar(200,200,200) takes too many place on the image, the algorithm could set it as background color and it is removed from the image so the image should take small place. So when it takes same size as regular PNG or even more, that doesn't give any sense.
i am not an expert on this subject but tried to test some compression_params maybe you will find the answer by testing the code below.
probably adding the following lines will do the trick.
compression_params.push_back(IMWRITE_PNG_STRATEGY);
compression_params.push_back(IMWRITE_PNG_STRATEGY_DEFAULT);
or you can try other alternatives accordind to documentation
also i opened an issue
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
void createAlphaMat(Mat &mat)
{
CV_Assert(mat.channels() == 4);
for (int i = 0; i < mat.rows; ++i) {
for (int j = 0; j < mat.cols; ++j) {
Vec4b& bgra = mat.at<Vec4b>(i, j);
bgra[0] = UCHAR_MAX; // Blue
bgra[1] = saturate_cast<uchar>((float(mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX); // Green
bgra[2] = saturate_cast<uchar>((float(mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX); // Red
bgra[3] = saturate_cast<uchar>(0.5 * (bgra[1] + bgra[2])); // Alpha
}
}
}
int main( int argc, char** argv )
{
// Create mat with alpha channel
Mat mat(480, 640, CV_8UC4);
createAlphaMat(mat);
vector<int> compression_params;
compression_params.push_back(IMWRITE_PNG_COMPRESSION);
compression_params.push_back(0);
compression_params.push_back(IMWRITE_PNG_STRATEGY);
compression_params.push_back(IMWRITE_PNG_STRATEGY_DEFAULT);
for (int i = 0; i < 10; i++)
{
compression_params[1] = i;
imwrite(format("alpha%d.png",i), mat, compression_params);
}
return 0;
}

Hough Transformation OPENCV C++

http://inside.mines.edu/~whoff/courses/EENG512/lectures/HoughInOpenCV.pdf
Hi, i am going through the pdf tutorial in the link above.
I encounter problem on page 6 of the slides.
As we seee that the output of the code after inserting the canny edge detector, it should trace out all the edges on a photo.
I cannot get what is shown at page 6.
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
printf("Hello world\n");
// read an image
Mat imgInput = imread("a.png");
// create image window named "My Image"
namedWindow("My Image");
// Convert to gray if necessary
if (imgInput.channels() == 3)
cv::cvtColor(imgInput, imgInput, CV_BGR2GRAY);
// Apply Canny edge detector
Mat imgContours;
double thresh = 105; // try different values to see effect
Canny(imgInput, imgContours, 0.4*thresh, thresh); // low, high threshold
// show the image on window
imshow("My Image", imgInput);
// wait for xx ms (0 means wait until keypress)
waitKey(5000);
return 0;
}
And also, there is a line double thresh = xxx;//try different values
What values should i put? and what are the values mean?
Thank you
Just replace your imshow function with ,
imshow("My Image", imgContours);
and you can use thresh value approximately around 200.
Change threshold value and see effect of it and according to that you can select your threshold value.
The imgContours is your output map with all the edges. You should use imshow with imgContours.
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
printf("Hello world\n");
// read an image
Mat imgInput = imread("a.png");
// create image window named "My Image"
namedWindow("My Image");
// Convert to gray if necessary
if (imgInput.channels() == 3)
cv::cvtColor(imgInput, imgInput, CV_BGR2GRAY);
// Apply Canny edge detector
Mat imgContours;
double thresh = 105; // try different values to see effect
Canny(imgInput, imgContours, 0.4*thresh, thresh); // low, high threshold
// show the image on window
imshow("My Image", imgContours);
// wait for xx ms (0 means wait until keypress)
waitKey(5000);
return 0;
}
Reference:
http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=canny#canny

opencv imshow show only the image

I've switched from Ubuntu to Windows for my opencv project and while displaying an image using the imshow function the image is displayed but the other details like x axis and y axis information and the intensity values were not shown in the window.
The same code under the Ubuntu build works perfectly. Here is my code:
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main()
{
cv::Mat imgrgb = imread("C:\\Users\\Len\\Documents\\project\\Images\\1-11.jpg", CV_LOAD_IMAGE_COLOR);
// Check that the image read is a 3 channels image and not empty
CV_Assert(imgrgb.channels() == 3);
if (imgrgb.empty()) {
cout << "Image is empty. Specify correct path" << endl;
return -1;
}
cv::cvtColor(imgrgb, img, CV_BGR2GRAY);
namedWindow("Test", cv::WINDOW_AUTOSIZE);
imshow("Test", imgrgb);
waitKey(0);
}
So, how can I display the intensity values along with the current x and y axis information?

OpenCV C++ Mat to Integer

I'm pretty new to OpenCV, so bear with me. I'm running a Mac Mini with OSX 10.8. I have a program that recognizes colors and displays them in binary picture (black and white). However, I want to store the number of white pixels as an integer (or float, etc.) to compare with other number of pixels. How can I do this? Here is my current code-
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
VideoCapture cap(0); //capture the video from webcam
if ( !cap.isOpened() ) // if not success, exit program
{
cout << "Cannot open the web cam" << endl;
return -1;
}
namedWindow("HSVLeftRed", CV_WINDOW_AUTOSIZE);
namedWindow("HSVLeftGreen", CV_WINDOW_AUTOSIZE);
while (true) {
Mat image;
cap.read(image);
Mat HSV;
Mat leftgreen;
Mat leftred;
//Left Cropping
Mat leftimg = image(Rect(0, 0, 640, 720));
//Left Red Detection
cvtColor(leftimg,HSV,CV_BGR2HSV);
inRange(HSV,Scalar(0,0,150),Scalar(0,0,255), leftgreen);
//imshow("HSVLeftRed", leftgreen);
//print pixel type
//Left Green Detection
cvtColor(leftimg,HSV,CV_BGR2HSV);
inRange(HSV,Scalar(still need to find proper min values),Scalar(still need to find proper max values), leftgreen);
//imshow("HSVLeftGreen", leftgreen);
//compare pixel types
}
return 0;
}
Thanks in advance!
To count the non-zero pixels, OpenCV has this function cv::countNonZero. It takes input the image, whose number of non-zero pixels, we want to calculate and output is number of non-zero pixels(int). Here is the documentation.
In your case, since all the pixels are either black or white, all the non zero pixels will be white pixels.
This is how to use it,
int cal = countNonZero(image);
Change image, as per your code.