I am trying to edit the pixels of an image with opencv.
I used this code:
#include<iostream>
#include<opencv2/opencv.hpp>
#include<stdint.h>
using namespace std;
uchar* array123()
{
uchar arr[3] = { 123, 123, 123 };
return arr;
};
int main()
{
cv::Mat img = cv::imread("img.jpg");
uchar* n;
for (int x = 0; x < img.cols; x++)
{
for (int y = 0; y < img.rows; y++)
{
n = array123();
cout << "n " << (int)*n << " " << (int)*(n + 1) << " " << (int)*(n + 2) << endl;
cv::Vec3b& color = img.at<cv::Vec3b>(y, x);
cout << "Before change " << (int)color[0] << " " << (int)color[1] << " " << (int)color[2] << endl;
color[0] = *n;
color[1] = *(n + 1);
color[2] = *(n + 2);
img.at<cv::Vec3b>(y, x) = color;
cv::Vec3b color2 = img.at<cv::Vec3b>(y, x);
cout << "After change " << (int)color2[0] << " " << (int)color2[1] << " " << (int)color2[2] << endl;
}
}
}
The console will log something like this:
n 123 123 123
Before change 153 123 26
After change 204 204 204
... repeating with After change always being 204 204 204 ...
And if I save the image is just a gray image with 204, 204, 204 RGB values
Does anyone know why this happens?
Related
My code is like this so far :
void matrix::print(int colWidth) const
{
cout << getRows() << " x " << getCols() << endl;
cout << "-";
for (unsigned int d = 0; d < getCols(); d++) {
cout << "--------";
}
cout << endl;
for (unsigned x = 0; x < getRows(); x++) {
cout << "|";
for (unsigned y = 0; y < getCols(); y++) {
cout << setw(colWidth) << at(x, y) << " |";
}
cout << endl;
}
cout << "-";
for (unsigned int d = 0; d < getCols(); d++) {
cout << "--------";
}
cout << endl;
}
But the output depends on the colWidth which will be the space between each number printed. So how can I adjust my dashes to be printed like the following no matter the colWidth it should align.
One output should look like this:
Second output is like this:
If the column width is a parameter, you're almost done with your code. Just turn the cout<<"--------" into:
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-');
That code prints a string of dashes, which width is: number of matrix columns, times column width plus 2, plus 1:
Plus 2 because you are appending a " |" to each column.
Plus 1 because you are adding a '|' at the beginning of each row.
You may want to check for empty matrices at the beginning of your print method.
[Demo]
#include <initializer_list>
#include <iomanip> // setw
#include <iostream> // cout
#include <vector>
class matrix
{
public:
matrix(std::initializer_list<std::vector<int>> l) : v{l} {}
size_t getRows() const { return v.size(); }
size_t getCols() const { if (v.size()) { return v[0].size(); } return 0; }
int at(size_t x, size_t y) const { return v.at(x).at(y); }
void print(int colWidth) const
{
std::cout << "Matrix: " << getRows() << " x " << getCols() << "\n";
// +2 due to " |", +1 due to initial '|'
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-') << "\n";
for (unsigned x = 0; x < getRows(); x++) {
std::cout << "|";
for (unsigned y = 0; y < getCols(); y++) {
std::cout << std::setw(colWidth) << at(x, y) << " |";
}
std::cout << "\n";
}
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-') << "\n";
}
private:
std::vector<std::vector<int>> v{};
};
int main()
{
matrix m{{1, 2}, {-8'000, 100'000}, {400, 500}};
m.print(10);
}
// Outputs
//
// Matrix: 3 x 2
// -------------------------
// | 1 | 2 |
// | -8000 | 100000 |
// | 400 | 500 |
// -------------------------
The program I am trying to make is supposed to calculate and display each entry of the fibonacci sequence up to the 40th.
I believe I'm nearly there in terms of getting this done. The issue is: after the numbers 1 and 2, the sequence just seems to reset itself and leaves every subsequent number 1 place behind in the sequence.
This is the code:
#include <iostream>
using namespace std;
int main()
{
int a = 0;
int b = 1;
for (int i = 0; i < 40; ++i)
{
if (i==1)
{
cout << i << " " << b << endl;
}
else if (i==2)
{
cout << i << " " << b*2 << endl;
}
else
{
int c = a + b;
a = b;
b = c;
cout << i << " " << c << endl;
}
}
return 0;
}
I pre-programmed the first couple of numbers in the sequence because I couldn't get them to work properly, but after doing this, it seems to throw off the rest of the program.
The output from the code is this:
0 1
1 1
2 2
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
20 6765
21 10946
22 17711
23 28657
24 46368
25 75025
26 121393
27 196418
28 317811
29 514229
30 832040
31 1346269
32 2178309
33 3524578
34 5702887
35 9227465
36 14930352
37 24157817
38 39088169
39 63245986
It seems that I have solved this issue instantly after creating the post.
I decided to try pre-program the very first entry in the sequence (0) to be one, and completely remove the other pre-programmed parts in the sequence. This solved the entire thing.
Here's the working code:
#include <iostream>
using namespace std;
int main()
{
int a = 0;
int b = 1;
for (int i = 0; i < 40; ++i)
{
if (i == 0)
{
cout << i << " " << b << endl;
}
else
{
int c = a + b;
a = b;
b = c;
cout << i << " " << c << endl;
}
}
return 0;
}
You forgot to set a for the second case.
So when b = 2, c uses previous value of a which is 0.
Therefore, c = a+b = 0 + 2 = 2.
Set a = 1 in you second case:
else if (i==2)
{
a = 1 // This
cout << i << " " << b*2 << endl;
}
I pre-programmed the first couple of numbers in the sequence.. If you wish to go along this way, the following could be another method..
#include <iostream>
using namespace std;
int main()
{
int a = 0;
int b = 1;
cout << 0 << " " << a << endl;//simply display the preprogrammed numbers
cout << 1 << " " << b << endl;
for (int i = 2; i < 40; ++i)//apply the formula for remaining elements
{
int c = a + b;
a = b;
b = c;
cout << i << " " << c << endl;
}
return 0;
}
Try the following changes in your program.
#include <iostream>
using namespace std;
int main() {
int a = 0;
int b = 1;
for (int i = 0; i < 40; ++i)
{
if (i==0)
{
cout << i << " " << a << endl;
}
else if (i==1)
{
cout << i << " " << b << endl;
}
else
{
int c = a + b;
a = b;
b = c;
cout << i << " " << c << endl;
}
}
return 0;
}
In the following snippet, when I print the posUVZ values, they are non-zero but after I pass them to ProjectDepthToCamera(wxhDepth, posUVZ, pos3D) all the pos3D values happen to be zero. Any though on why is this happening and how to fix it?
/***
Reads the depth data from the sensor and fills in the matrix
***/
void SR300Camera::fillInZCoords()
{
PXCImage::ImageData depthImage;
PXCImage *depthMap = sample->depth;
depthMap->AcquireAccess(PXCImage::ACCESS_READ, &depthImage);
PXCImage::ImageInfo imgInfo = depthMap->QueryInfo();
int depth_stride = depthImage.pitches[0] / sizeof(pxcU16);
Projection * projection = device->CreateProjection();
unsigned int wxhDepth = depth_width * depth_height;
// create the array of depth coordinates + depth value (posUVZ) within the defined ROI
PXCPoint3DF32* posUVZ = new PXCPoint3DF32[wxhDepth];
pxcU16 *dpixels = (pxcU16*)depthImage.planes[0];
unsigned int dpitch = depthImage.pitches[0] / sizeof(pxcU16); /* aligned width */
for (unsigned int yy = 0, k = 0; yy < depth_height; yy++)
{
for (unsigned int xx = 0; xx < depth_width; xx++, k++)
{
posUVZ[k].x = (pxcF32)xx;
posUVZ[k].y = (pxcF32)yy;
posUVZ[k].z = (pxcF32)dpixels[yy * dpitch + xx];
// cout << "xx is " << posUVZ[k].x << endl;
// cout << "yy is " << posUVZ[k].y << endl;
// cout << "zz is " << posUVZ[k].z<< endl;
}
}
// convert the array of depth coordinates + depth value (posUVZ) into the world coordinates (pos3D) in mm
PXCPoint3DF32* pos3D = new PXCPoint3DF32[wxhDepth];
projection->ProjectDepthToCamera(wxhDepth, posUVZ, pos3D);
/*
if (projection->ProjectDepthToCamera(wxhDepth, posUVZ, pos3D) < PXC_STATUS_NO_ERROR)
{
delete[] posUVZ;
delete[] pos3D;
cout << "projection unsucessful";
return;
}
*/
for (unsigned int yy = 0, k = 0; yy < depth_height; yy++)
{
for (unsigned int xx = 0; xx < depth_width; xx++, k++)
{
cout << "xx is " << pos3D[k].x*1000.0 << endl;
cout << "yy is " << pos3D[k].y*1000.0 << endl;
cout << "zz is " << pos3D[k].z*1000.0 << endl;
xyzBuffer.push_back(cv::Point3f(pos3D[k].x, pos3D[k].y, pos3D[k].z));
}
}
/*
for (int idx = 0; idx < wxhDepth; idx++) {
cout << "x is " << pos3D[idx].x*1000.0 << endl;
cout << "y is " << pos3D[idx].y*1000.0 << endl;
cout << "z is " << pos3D[idx].z*1000.0 << endl;
xyzBuffer.push_back(cv::Point3f(pos3D[idx].x, pos3D[idx].y, pos3D[idx].z));
}
*/
//xyzMap = cv::Mat(xyzMap.size(), xyzMap.type, &pos3D);
xyzMap = cv::Mat(xyzBuffer);
cout << "xyzMap = " << endl << " " << xyzMap << endl << endl;
projection->Release();
delete[] posUVZ;
delete[] pos3D;
};
Here's the correct answer to get the xyzMap from the Depth image UVmap:
PXCImage::ImageData depthImage;
depthMap->AcquireAccess(PXCImage::ACCESS_READ, &depthImage);
PXCImage::ImageInfo imgInfo = depthMap->QueryInfo();
depth_width = imgInfo.width;
depth_height = imgInfo.height;
num_pixels = depth_width * depth_height;
PXCProjection * projection = device->CreateProjection();
PXCPoint3DF32 *pos3D = new PXCPoint3DF32[num_pixels];
sts = projection->QueryVertices(depthMap, &pos3D[0]);
if (sts < Status::STATUS_NO_ERROR) {
wprintf_s(L"Projection was unsuccessful! \n");
sm->Close();
}
I need to generate points around a quarter circle in the anticlockwise direction but with my program I'm able to generate in clockwise direction. Below is my code.
#include <iostream>
#include <cmath>
#include <fstream>
#include <iomanip>
using namespace std;
int main ()
{
int NumberPoints(10);
double x1;
const double PI = 3.14159;
double radius = 5;
double angle = 0.7853; //45 degrees
ofstream plot;
string plotDataFile("points.txt");
plot.open(plotDataFile.c_str());
for (int i = 0; i <= NumberPoints; i++)
{
x1 = angle/NumberPoints*i;
plot << setprecision(5) << radius * sin(x1) << " ";
plot << setprecision(5) << radius * cos(x1) << " " << endl;
}
plot.close();
}
I get the following output.
0 5
0.39225 4.9846
0.78208 4.9385
1.1671 4.8619
1.5449 4.7553
1.9132 4.6195
2.2697 4.4552
2.6122 4.2634
2.9386 4.0453
3.2469 3.8023
3.5352 3.5359
I need points in the format
3.5352 3.5359
3.2469 3.8023
2.9386 4.0453
.
.
0 5
Could someone help me modify my code or give me an idea for the same.
How about this?
for (int i = NumberPoints; i >= 0; i--)
{
x1 = angle/NumberPoints*i;
plot << setprecision(5) << radius * sin(x1) << " ";
plot << setprecision(5) << radius * cos(x1) << " " << endl;
}
Instead of
for (int i = 0; i <= NumberPoints; i++)
use
for (int i = NumberPoints; i >= 0; i--)
just iterate backwards:
for (int i = NumberPoints; i >= 0; i--)
By the way, your variable NumberPoints has probably wrong name. Notice that you are getting 11 points, not 10.
may be help
Input:
0 5
0.39225 4.9846
0.78208 4.9385
std::vector< std::pair< std::string, std::string > > pair_of_point;
pair_of_point.emplace_back("0", "5");
pair_of_point.emplace_back("0.39225", "4.9846");
pair_of_point.emplace_back("0.78208", "4.9385");
std::reverse( pair_of_point.begin(), pair_of_point.end()) ;
std::cout << pair_of_point[ 0 ].first << " " << pair_of_point[ 0 ].second << std::endl;
std::cout << pair_of_point[ 1 ].first << " " << pair_of_point[ 1 ].second << std::endl;
std::cout << pair_of_point[ 2 ].first << " " << pair_of_point[ 2 ].second << std::endl;
output
0.78208 4.9385
0.39225 4.9846
0 5
Instead of std::string enter you date-type
I'm trying to write a program with opencv and C++. I have an image and I am trying to get the saturation value of determined pixel which is in the (x, y) point. I use the next sentence to do it:
saturation_level = hsv_chanels[1].at<uchar>(x, y);
The thing is that the program builds OK, but when I try to run, it sometimes works fine and sometimes terminates with this error:
Segmentation fault: 11
Do someone know why this error is appearing? I read that this error appears because of the my computer memory but I don't know why it only appears sometimes.
EDIT:
This is the function I call to find the homography:
Mat ObtenHomografiaSuelo (vector <KeyPoint> keypoints1, vector <KeyPoint> keypoints2, Mat imagen1, Mat imagen2){
//*****************************************************************************
//Find homography mat
//*****************************************************************************
vector < Point2f > image_points[2];
int cont = 0;
vector<Mat> chanels_hsv1; //[0]->H, [1]->S, [2]->V
split( image1, chanels_hsv1 );
vector<Mat> chanels_hsv2;
split( image2, chanels_hsv2 );
for(vector<KeyPoint>::const_iterator it = keypoints1.begin(); it!= keypoints1.end(); ++it){
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
cout << "1" << endl;
float saturation_level = chanels_hsv1[1].at<uchar>(x, y);
cout << "2" << endl;
double max_level = 70.0;
cout << "3" << endl;
if ((y < camSize.height/4) && (saturatio_level < max_level) ){
cout << "1:" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[0].push_back(Point2f(x,y));
cout << "done" << endl;
cont ++;
}
}
cont = 0;
for (vector<KeyPoint>::const_iterator it = keypoints2.begin(); it!=keypoints2.end(); ++it) {
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
float saturation_level = chanels_hsv2[1].at<uchar>(x, y);
double max_level = 70.0;
if ((y < (camSize.height)/4) && (saturation_level < max_level)){
cout << "2" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[1].push_back(Point2f(x,y));
cont ++;
}
}
cout << "We are obtain: " << cont << " points to do the homography" << endl;
waitKey();
Mat H;
H = Mat::zeros(4, 4, CV_64F);
if (cont < 4) {
cout << "Few points to do the homography" << endl;
}
else{
if (image_points[0].size() > image_points[1].size()){
image_points[0].resize(image_points[1].size());
}
else if (image_points[1].size() > image_points[0].size()){
image_points[1].resize(image_points[0].size());
}
H = findHomography (image_points[0], image_points[1], CV_RANSAC, 3);
cout << "done_matrix" << endl;
}
return H;
}
Before to call the function I detect keypoints using Harris or any other detector and the image I passed to the function is a HSV_image converted by cvtColor function.
The error appears in the line that I mentioned before because in the terminal I can se:
1
Segmentation Fault: 11
I've just finished to correct the error, I think it was because I wasn't using efficiently my function. I was using two 'for' staments to cross my two vectors of keypoints detected and the errors sometimes appears at first and others at second one. I don't really know why was the error, I just change my code to do the same think more efficiently and finally it works.
I just changed this lines:
for(vector<KeyPoint>::const_iterator it = keypoints1.begin(); it!= keypoints1.end(); ++it){
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
cout << "1" << endl;
float saturation_level = chanels_hsv1[1].at<uchar>(x, y);
cout << "2" << endl;
double max_level = 70.0;
cout << "3" << endl;
if ((y < camSize.height/4) && (saturatio_level < max_level) ){
cout << "1:" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[0].push_back(Point2f(x,y));
cout << "done" << endl;
cont ++;
}
cont = 0;
for (vector<KeyPoint>::const_iterator it = keypoints2.begin(); it!=keypoints2.end(); ++it) {
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
float saturation_level = chanels_hsv2[1].at<uchar>(x, y);
double max_level = 70.0;
if ((y < (camSize.height)/4) && (saturation_level < max_level)){
cout << "2" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[1].push_back(Point2f(x,y));
cont ++;
}
}
by this ones:
for (int i = 0; i < good_matches.size(); i++) {
int idx1=good_matches[i].queryIdx;
int idx2=good_matches[i].trainIdx;
if (((keypoints[0][idx1].pt.y < (camSize.height/4)) && (canales_hsv1[1].at<uchar>(keypoints[0][idx1].pt.x, keypoints[0][idx1].pt.y) < nivel_maximo)) || ((keypoints[1][idx2].pt.y < (camSize.height/4)) && (canales_hsv2[1].at<uchar>(keypoints[1][idx1].pt.x, keypoints[1][idx2].pt.y) < nivel_maximo)) ) {
cout << "entro" << endl;
matched_points[0].push_back(keypoints[0][idx1].pt);
matched_points[1].push_back(keypoints[1][idx2].pt);
contador ++;
}
}
Currently I only cross the matched keypoints instead of all the keypoints, it requires less computers operations and now it works OK.