I am trying to get a calibration program for captured thermal video converted from python to C++, and the first step in the process is binning the pixels in the image down from 480x640 to 240x320, so pixel bins of 2x2. The returned image after binning (using the same logic from the correctly functioning python version) the image being returned is the left half of the image stretched across the width of the image, rather than giving the whole image only at the smaller resolution.
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/videoio/videoio.hpp>
#include <opencv2/video.hpp>
#include <opencv2/imgcodecs.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat binImg(Mat);
int asInt(uint8_t);
uint8_t as8bit(int);
Mat rotate(Mat, double);
int main(int argc, char *argv[]){
VideoCapture cap(argv[1]);
int frameCount = cap.get(cv::CAP_PROP_FRAME_COUNT);
int frameWidth = cap.get(cv::CAP_PROP_FRAME_WIDTH);
int frameHeight = cap.get(cv::CAP_PROP_FRAME_HEIGHT);
Mat buf [frameCount]; //create new array of Mat for the calibrated video
int fc = 0;
VideoWriter video("cppThermalTest.avi",CV_FOURCC('X','V','I','D'), 15, Size(240, 320), false); //create empty video #15fps, 320x240, isColor=false
while (fc < frameCount){
Mat frame(640, 480, CV_8UC1, Scalar(70));
cap >> frame;
Mat temp = binImg(frame);//bin the frame
imshow("test", temp);
imwrite("test.jpg", temp);
waitKey(0);
video.write(temp); //write the binned frame to the video
cout << fc << endl;
fc++;
}
cap.release();
video.release();
return 0;
}
Mat binImg(Mat frame){
int frameWidth = frame.cols / 2; //480 / 2
int frameHeight = frame.rows / 2; //640 / 2
cout << frameHeight << " " << frameWidth << endl;
Mat binFrame(frameHeight, frameWidth, CV_8UC1);
for(int i=0; i<binFrame.rows; i++){
for(int j=0; j<binFrame.cols; j++){
int ul = asInt(frame.at<uint8_t>((2*i),(2*j)));
int bl = asInt(frame.at<uint8_t>(((2*i)+1),(2*j)));
int ur = asInt(frame.at<uint8_t>((2*i), ((2*j)+1)));
int br = asInt(frame.at<uint8_t>(((2*i)+1),((2*j)+1)));
int avg = (ul + ur + bl + br) / 4;
binFrame.at<uint8_t>(i,j) = as8bit(avg); //set the matrix element to the new value
}
}
return binFrame;
}
int asInt(uint8_t val){
//convert unsigned 8 bit int to int
int temp = val;
return temp;
}
uint8_t as8bit(int val){
//convert int to unsigned 8 bit int
uint8_t temp = val;
return temp;
}
Mat rotate(Mat src, double angle){ //rotate function returning mat object with parametres imagefile and angle
Mat dst; //Mat object for output image file
Point2f pt(src.cols/2., src.rows/2.); //point from where to rotate
Mat r = getRotationMatrix2D(pt, angle, 1.0); //Mat object for storing after rotation
warpAffine(src, dst, r, Size(src.cols, src.rows)); ///applie an affine transforation to image.
return dst; //returning Mat object for output image file
}
After playing around with things for a while, I found that when doing "at" calls, specifying 0 as a third parameter (e.g. binFrame.at<uint8_t>(i,j, 0) = as8bit(avg);) fixes the issue.
Related
So I am trying to edit all the frames from input video and than save them to the output. The saved video appears and has the proper filesize but can't open and the imshow inside the while doesn't show the frames at all (only a blank window). I've tried numerous codecs (H264,MJPG,MPEG,MPV4,XVID,CVID) and non of them make it work. What could be the problem? Also, the first function is for converting RGB to YUV and returning the gray channel, while the second one works with HPF and LPF. These functions work on individual images so I don't think they are the problem.
#include <opencv2\opencv.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
Mat KonverzijaRGB2YUV(Mat ulazniFrejm){
int width = ulazniFrejm.cols;
int height = ulazniFrejm.rows;
Mat konvertovan(height, width, CV_8UC3, Scalar(0,0,0));
for(int i=0; i<width; i++){
for(int j=0; j<height; j++){
double R = ulazniFrejm.at<Vec3b>(j,i).val[0];
double G = ulazniFrejm.at<Vec3b>(j,i).val[1];
double B = ulazniFrejm.at<Vec3b>(j,i).val[2];
double Y = 0.299*R + 0.587*G + 0.114*B;
double U = 0.436*(B-Y) / (1-0.114);
double V = 0.615*(R-Y) / (1-0.299);
konvertovan.at<Vec3b>(j,i).val[0] = Y;
konvertovan.at<Vec3b>(j,i).val[1] = U;
konvertovan.at<Vec3b>(j,i).val[2] = V;
}
}
Mat Ykanal[3];
split (konvertovan, Ykanal);
Mat YkanalRGB;
cvtColor(Ykanal[0], YkanalRGB, CV_GRAY2RGB);
return YkanalRGB;
}
Mat Izostravanje(Mat ulazniFrejm){
Mat izostrena;
float valLaplas[] =
{ 0.,-1.,0.,
-1.,4.,-1.,
0.,-1.,0. };
Mat kernelLaplas(Size(3,3), CV_32FC1, valLaplas);
Mat Laplas;
filter2D(ulazniFrejm, Laplas, -1, kernelLaplas);
convertScaleAbs(Laplas, Laplas);
Mat Gaus;
GaussianBlur(ulazniFrejm, Gaus, Size(3,3), 0, 0);
addWeighted(Laplas, 1.4, Gaus, 1.0, 0, izostrena);
return izostrena;
}
int main(int argc, char** argv){
VideoCapture ulazniVideo("esmeralda.mp4");
int brojFrejmova = static_cast<int>(ulazniVideo.get(CV_CAP_PROP_FRAME_COUNT));
if(!ulazniVideo.isOpened()){
cout << "Video se ne moze otvoriti" << endl;
}
waitKey(1000);
Size frameSize = Size((int)ulazniVideo.get(CV_CAP_PROP_FRAME_WIDTH), (int)ulazniVideo.get(CV_CAP_PROP_FRAME_HEIGHT));
int fps = ulazniVideo.get(CV_CAP_PROP_FPS);
int ex = -1;
VideoWriter izlazniVideo;
izlazniVideo.open("esmeralda.mp4", ex, fps, frameSize, true);
int brojac = 0;
while(true){
Mat frame;
ulazniVideo >> frame;
Mat konvertovanFrejm;
konvertovanFrejm = KonverzijaRGB2YUV(frame);
Mat izostrenFrejm;
izostrenFrejm = Izostravanje(konvertovanFrejm);
if(frame.empty()){
break;
}
izlazniVideo << frame;
brojac++;
namedWindow("Video", CV_WINDOW_AUTOSIZE);
imshow("Video", izostrenFrejm);
int waitKey(1000/fps);
}
waitKey(0);
return 0;
}
I am trying to take out the ground and make grids on it for path mapping and insert it back to the image. Here I am using findhomography and warpPerspective functions to do so. But when I switch the points for inserting back the modified plane, everything except the plane becomes black in the image.
I have tried to do it using an intermediate image but the result is the same.
#include "pch.h"
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
struct userdata {
Mat im;
vector<Point2f> points;
};
void mouseHandler(int event, int x, int y, int flags, void* data_ptr)
{
if (event == EVENT_LBUTTONDOWN) {
userdata* data = ((userdata*)data_ptr);
circle(data - > im, Point(x, y), 3, Scalar(0, 0, 255), 5, LINE_AA);
imshow("Image", data - > im);
if (data - > points.size() < 4) {
data - > points.push_back(Point2f(x, y));
}
}
}
int main(int argc, char** argv)
{
// Read source image.
Mat im_src = imread("imagesindoor.jpg");
// Destination image. The aspect ratio of the book is 3/4
Size size(400, 300);
Size size2(im_src.cols, im_src.rows);
Mat im_dst = Mat::zeros(size, CV_8UC3);
// Create a vector of destination points.
vector<Point2f> pts_dst;
pts_dst.push_back(Point2f(0, 0));
pts_dst.push_back(Point2f(size.width - 1, 0));
pts_dst.push_back(Point2f(size.width - 1, size.height - 1));
pts_dst.push_back(Point2f(0, size.height - 1));
// Set data for mouse event
Mat im_temp = im_src.clone();
userdata data;
data.im = im_temp;
cout << "Click on the four corners of the book -- top left first and" <<
endl
<< "bottom left last -- and then hit ENTER" << endl;
// Show image and wait for 4 clicks.
imshow("Image", im_temp);
// Set the callback function for any mouse event
setMouseCallback("Image", mouseHandler, &data);
waitKey(0);
// Calculate the homography
Mat h = getPerspectiveTransform(data.points, pts_dst);
// Warp source image to destination
warpPerspective(im_src, im_dst, h, size);
// changing clor of im_dst
for (int i = 0; i < im_dst.rows; i++) {
for (int j = 0; j < im_dst.cols; j++) {
//apply condition here
im_dst.at<cv::Vec3b>(i, j) = 255;
}
}
Mat p = getPerspectiveTransform(pts_dst, data.points);
warpPerspective(im_dst, im_src, p, size2);
// Show image
//imshow("Image", im_dst);
imshow("Image2", im_src);
waitKey(0);
return 0;
}
addWeighted can be used to blend the current result with the source image to get the expected result.
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
struct userdata {
Mat im;
vector<Point2f> points;
};
void mouseHandler(int event, int x, int y, int flags, void* data_ptr)
{
if (event == EVENT_LBUTTONDOWN) {
userdata* data = ((userdata*)data_ptr);
circle(data-> im, Point(x, y), 3, Scalar(0, 0, 255), 5, LINE_AA);
imshow("Image", data->im);
if (data-> points.size() < 4) {
data-> points.push_back(Point2f(x, y));
}
}
}
int main(int argc, char** argv)
{
// Read source image.
Mat im_src = imread("test.png");
// Destination image. The aspect ratio of the book is 3/4
Size size(400, 300);
Size size2(im_src.cols, im_src.rows);
Mat im_dst = Mat::zeros(size, CV_8UC3);
// Create a vector of destination points.
vector<Point2f> pts_dst;
pts_dst.push_back(Point2f(0, 0));
pts_dst.push_back(Point2f(size.width - 1, 0));
pts_dst.push_back(Point2f(size.width - 1, size.height - 1));
pts_dst.push_back(Point2f(0, size.height - 1));
// Set data for mouse event
Mat im_temp = im_src.clone();
userdata data;
data.im = im_temp;
cout << "Click on the four corners of the book -- top left first and" <<
endl
<< "bottom left last -- and then hit ENTER" << endl;
// Show image and wait for 4 clicks.
imshow("Image", im_temp);
// Set the callback function for any mouse event
setMouseCallback("Image", mouseHandler, &data);
waitKey(0);
// Calculate the homography
Mat h = getPerspectiveTransform(data.points, pts_dst);
// Warp source image to destination
warpPerspective(im_src, im_dst, h, size);
// changing clor of im_dst
for (int i = 0; i < im_dst.rows; i++) {
for (int j = 0; j < im_dst.cols; j++) {
//apply condition here
im_dst.at<cv::Vec3b>(i, j) = 255;
}
}
Mat t;
Mat p = getPerspectiveTransform(pts_dst, data.points);
warpPerspective(im_dst, t, p, size2);
// Show image
//imshow("Image", im_dst);
std::cout << "t :" <<t.cols << ", " <<t.rows <<std::endl;
Mat final;
addWeighted(im_src, 0.5, t, 0.5, 0, final);
imshow("Image2", final);
waitKey(0);
return 0;
}
When running this code with the same image and mask I occasionally get values that differ previously. For example
Normal/Expected Results
Abnormal Results
As can be seen in the two results I somehow receive negative RGB values. The Abnormal Results show up around every 5-8 runs for the exact same image with the exact same mask.
What do I need to change to prevent the occasional abnormal result?
#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string>
using namespace cv;
using namespace std;
float get_color(Mat img,Mat &mask){
Mat img1 = img;
Mat hist;
int dims = 1;
int histSize = 255;
float hranges[] = { 0, 255 };
const float *ranges = {hranges};
calcHist(&img1,1,0,mask,hist, dims, &histSize, &ranges ,true ,false);
int sum=0;
for(int i = 0;i<256;i++){
sum += hist.at<float>(i,0);
}
Mat weights = hist/sum;
float hist_avg=0.0;
for(int i = 0;i<256;i++){
hist_avg += i*weights.at<float>(i,0);
}
return hist_avg;
}
int main(int argc, char** argv){
Mat aa = imread("/Users/dnguyen/Desktop/snapshot207042/pic.jpg", CV_LOAD_IMAGE_COLOR);
vector<Mat> bgr;
split(aa, bgr);
Mat b = bgr[0];
Mat g = bgr[1];
Mat r = bgr[2];
for(unsigned int i=1;i<23;i++){
stringstream ss;
ss << i;
string str = ss.str();
string file_name = "/Users/dnguyen/Desktop/okay/data/card_masks/"+str+"_mask.png";
Mat mask = imread(file_name,0);
Mat cc;
threshold(mask,cc,90,255,THRESH_BINARY);
float b_avg = get_color(b, cc);
float g_avg = get_color(g, cc);
float r_avg = get_color(r, cc);
cout << b_avg << ","<< g_avg << "," << r_avg << endl;
}
}
I want to use the active contour OpenCV function. I have been trying different code but I cant figure out how to get the snake to run across the image. When I run the code below I receive the same points as the line I drew across the image. How can I check to see if the snake is actually running.
//USED TO OPEN IMAGE
#include "opencv2/highgui/highgui.hpp"
//USED TO GAUSSIAN FILTER
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include <iostream>
#include <fstream>
#include "opencv2/legacy/legacy.hpp"
#include <cstdlib>
using namespace std;
using namespace cv;
void myLine(Mat copy, Point pt1, Point pt2);
void Extract(Mat copy, Point pt1, Point pt2);
void readFile(Mat copy);
void snake(Mat copy, CvPoint* pointsA);
//void ActiveSnake(Mat copy, Point pt1, Point pt2);
int main(){
//CODE TO LOADING IMAGE
Mat frame = imread ("First.png", CV_LOAD_IMAGE_GRAYSCALE);
//putText(frame,"First", Point (120, 330), 1, 4, CV_RGB(255, 0, 0), 3, 8, false);
int rows = frame.rows;
int cols = frame.cols;
//If the image wont appear
if (frame.empty())
{
cout<<"No Image!"<<endl;
return -1;
}
//Cloning
Mat copy = frame.clone();
//Gaussian Filter (Originial Image, Clone Image, KSize(MUST BE POSITIVE OR ODD OR ZERO width, height), sigmaX, sigmaY
GaussianBlur(frame, copy, Size(9, 9), 0, 0);
Point pt1, pt2;
pt1.x = 0;
pt1.y = 95;
pt2.x = 900;
pt2.y = 95;
Extract (copy, pt1, pt2);
readFile(copy);
return 0;
}
void myLine (Mat copy, Point start, Point end)
{
int thickness = 2;
int lineType = 8;
line (copy, start, end, Scalar(0,0,0), thickness, lineType);
}
void Extract (Mat copy, Point pt1, Point pt2)
{
myLine(copy, Point(pt1), Point (pt2));
ofstream myfile;
myfile.open ("Test1.txt");
int copypt1x;
copypt1x = pt1.x;
for (int i = pt1.x; i <=pt2.x; i++){
for ( int j = pt1.y; 1 <=pt2.y; j++)
{
int copypt1y = pt1.y;
myfile <<copypt1x<<"\t"<<copypt1y<<endl;
}
copypt1x= copypt1x +1;
cout<<"\n";
}
myfile.close();
}
void readFile(Mat copy)
{
ifstream myfile;
CvPoint pointsA [1000];
myfile.open("Test1.txt");
if (!myfile.is_open()){
exit(EXIT_FAILURE);
}
int i = 0;
myfile >> pointsA[i].x>>pointsA[i].y;
while (myfile.good()){
i++;
myfile >> pointsA[i].x>>pointsA[i].y;
}
snake(copy, pointsA);
}
void snake(Mat copy, CvPoint* pointsA)
{
//IplImage* image2;
//image2 = cvCloneImage(&(IplImage)copy);
IplImage* image2;
image2 = cvCreateImage(cvSize(copy.cols,copy.rows),8,3);
IplImage ipltemp=copy;
cvCopy(&ipltemp,image2);
float alpha = 0.5; // Weight of continuity energy
float beta = 0.5; // Weight of curvature energy
float gamma = 0.9; // Weight of image energy
CvSize size; // Size of neighborhood of every point used to search the minimumm have to be odd
size.width = 5;
size.height = 5;
CvTermCriteria criteria;
criteria.type = CV_TERMCRIT_ITER; // terminate processing after X iteration
criteria.max_iter = 10000;
criteria.epsilon = 0.1;
int cpt = 1000;
cvSnakeImage(image2, pointsA, cpt, &alpha, &beta, &gamma, CV_VALUE, size, criteria, 0);
}
I am trying to generate a point cloud with my Minoru3D stereo camera, but it does not work.
The generated points are definitely not correct.
The camera is correctly calibrated.
My rectified images(rec1, rec2), the disparity map(disp) and the depth map(depth):
And the pointcloud:
I create the depth image with reprojectImageTo3D and then read the points at every pixel.
Full Code:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/contrib/contrib.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include "libcam.h"
#include <stdio.h>
#include <fstream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
// The camera properties
int w = 640;
int h = 480;
int fps = 20;
// The images, which are proceeded
Mat img1, img2;
// The grayscale versions of the images
Mat gray1, gray2;
// The disparity and depth map
Mat disparity;
Mat depth(Size(h, w), CV_32FC3);
// The iplImage versions of the images used to get the images from the camera
IplImage *iplImg1 = cvCreateImage(cvSize(w, h), 8, 3), *iplImg2 = cvCreateImage(cvSize(w, h), 8, 3);
// The cameras
Camera cam1("/dev/video0", w, h, fps), cam2("/dev/video1", w, h, fps);
// Load the camera model
Mat CM1, CM2, D1, D2, R, T, E, F, R1, R2, P1, P2, Q;
FileStorage fs("data/stereocalib.yml", FileStorage::READ);
fs["CM1"] >> CM1;
fs["CM2"] >> CM2;
fs["D1"] >> D1;
fs["D2"] >> D2;
fs["R"] >> R;
fs["T"] >> T;
fs["E"] >> E;
fs["F"] >> F;
fs["R1"] >> R1;
fs["R2"] >> R2;
fs["P1"] >> P1;
fs["P2"] >> P2;
fs["Q"] >> Q;
fs.release();
Mat map1x = Mat(h, w, CV_32F);
Mat map1y = Mat(h, w, CV_32F);
Mat map2x = Mat(h, w, CV_32F);
Mat map2y = Mat(h, w, CV_32F);
initUndistortRectifyMap(CM1, D1, R1, P1, cvSize(w, h), CV_32FC1, map1x, map1y);
initUndistortRectifyMap(CM2, D2, R2, P2, cvSize(w, h), CV_32FC1, map2x, map2y);
// The rectified images
Mat imgU1 = Mat(img1.size(), img1.type()), imgU2 = Mat(img2.size(), img2.type());
Ptr<StereoBM> sbm = createStereoBM(16 * 10, 5);
while (true) {
// Get the images from the cameras
cam1.Update();
cam2.Update();
cam1.toIplImage(iplImg1);
cam2.toIplImage(iplImg2);
img1 = cvarrToMat(iplImg1);
img2 = cvarrToMat(iplImg2);
// Rectify
remap(img1, imgU1, map1x, map1y, INTER_LINEAR, BORDER_CONSTANT, Scalar());
remap(img2, imgU2, map2x, map2y, INTER_LINEAR, BORDER_CONSTANT, Scalar());
// Convert the rectified images to grayscale images
cvtColor(imgU1, gray1, CV_BGR2GRAY);
cvtColor(imgU2, gray2, CV_BGR2GRAY);
// Create disparity map
sbm->compute(gray1, gray2, disparity);
// Create depth map
reprojectImageTo3D(disparity, depth, Q, true, CV_32F);
//imshow("img1", img1);
//imshow("img2", img2);
imshow("rec1", gray1);
imshow("rec2", gray2);
imshow("disp", disparity);
imshow("depth", depth);
int key = waitKey(10);
if (key == 'q') {
break;
}
else if (key == 's') {
stringstream output;
for (int x = 0; x < img1.rows; x++) {
for (int y = 0; y < img1.cols; y++) {
Point3f p = depth.at<Point3f>(x, y);
if(p.z >= 10000) continue; // Filter errors
output << p.x << "," << p.y << "," << p.z << endl;
}
}
ofstream outputFile("points");
outputFile << output.str();
outputFile.close();
cout << "saved" << endl;
}
else if (key == 'p') {
waitKey(0);
}
}
destroyAllWindows();
return 0;
}