What is the simplest way to modify a direct x,y location of a cv::Mat object? I have a cv::Mat called 'temp' which has an image in it, and what if I wanted to turn each pixel pink, one by one?
I tried something of the following:
for (int i = 0; i < temp.size().width; i++)
{
for (int j = 0; j < temp.size().height; j++)
{
temp.at(cv::Point(i, j)) = 255;
cv::waitKey();
}
}
but that won't even compile..
The way to use at in this case is temp.at<unsigned char>(i, j).
Here is an example :
Mat H(100, 100, CV_64F);
for(int i = 0; i < H.rows; i++)
for(int j = 0; j < H.cols; j++)
H.at<double>(i,j)=1./(i+j+1);
For the complete description look here: http://opencv.itseez.com/modules/core/doc/basic_structures.html#mat-at
Related
I have the following code:
void white(Mat&src,Mat&dst){
double h = src.cols;
double w = src.rows;
dst = src.clone();
for (int i = 0; i < dst.rows; i++) {
for (int j = 0; j < dst.cols; j++) {
dst.at<uchar>(i, j) = 255;
}
}
}
My expected result is to get a completely white image, however, I get this result:
Input Image:
Output Image:
It's a color image. Each pixel consists of 3 values. You have to set each color channel
void white(Mat&src,Mat&dst){
double h = src.cols;
double w = src.rows;
dst = src.clone();
for (int i = 0; i < dst.rows; i++) {
for (int j = 0; j < dst.cols; j++) {
for (std::size_t c = 0; c < 3; ++c) {
dst.at<Vec3b>(i, j)[c] = 255;
}
}
}
}
Is there a possibility to use a boost matrix along FFTW? if so how do you do it?
what i basically have is
QPixmap pixmap("lena.bmp");
// resize input image
pixmap = pixmap.copy(512,512,128,128);
pixmap = pixmap.scaled(128,128);
QImage image = pixmap.toImage();
QRgb col;
int g;
int width = pixmap.width();
int height = pixmap.height();
matrix<double> m(width,height);
for (int j = 0; j < m.size2(); j++)
{
for (int i = 0; i < m.size1(); i++)
{
m(i,j) = 0;
m(i,j) = qGray(image.pixel(i,j));
}
}
I want to perform FFTW on the matrix 'm' and then redisplay the fft of the image. how do i do this?
you can do is first read your image into an array, then apply the FFTW as per your needs on this array and then fill this array into a boost ublas matrix and then use it.
int a[width][height];
for (int j = 0; j < width; j++)
{
for (int i = 0; i < height; i++)
{
a[i][j] = qGray(image.pixel(i,j));
}
}
//apply fftw
matrix<double> m(width,height);
for (int j = 0; j < width; j++)
{
for (int i = 0; i < height; i++)
{
m(i,j) = fft_a[i][j];
}
}
I hope this works
How to convert Mat in 2d vector (vector of vector) in C++?
I tried this, and got error in Mat.at function.
vector<vector<double>> dctm(300, vector<double>(300,0));
for (int i = 0; i < 300; i++) {
for (int j = 0; j < 300; j++) {
dctm[i][j] = img.at<double>(i, j);
}
}
You can fill the vector by iterating over values and pushing them one by one, but in general this is not considered a good practice. Much better solution is to use range functions provided to you by stl. This is true not only for vector but for any other stl structure.
Cleaner (from stl point view) and faster solution should be like this:
for(int i=0; i<300; i++)
{
Mat r = img.row(i);
dctm.push_back(vector<double>(r.begin<unsigned char>(), r.end<unsigned char>()));
}
Much faster way would be
vector<vector<double>> dctm(300, vector<double>(300,0));
for (int i = 0; i < 300; i++) {
uchar *rowPtr = img.ptr<uchar>(i);
for (int j = 0; j < 300; j++) {
dctm[i][j] = *rowPtr[j];
}
}
See How to scan images, lookup tables and time measurement with OpenCV
I am trying to flip a gray scale image horizontally. Pointer fp is pointing to original image and pointer fp1 is creating horizontally flipped image. The Program is executing properly but the output image is worst...
for( i =0 ;i<width ; i++)
for(j=0; j <height; j++)
idata[i][height - 1 -j] = ( (unsigned char)fgetc(fp));
//flipping image
for( i =0 ;i<width ; i++)
for(j=0; j <height; j++)
putc(idata[i][j] , fp1);
there is no problem in header copy of image. i think problem is residing in for loop... plz help me out
Are you sure you are not mixing up width and height? The code seems to assume that the data is read in a column wise order when it most likely is in a row wise order. Try flipping the for loops and the dimension for flipping, like so:
for(j = 0; j < height; j++)
for(i = 0; i < width; i++)
idata[width - 1 - i][j] = ( (unsigned char)fgetc(fp));
//flipping image
for(j = 0; j < height; j++)
for(i = 0; i < width; i++)
putc(idata[i][j] , fp1);
I want to count the number of white points in a background image which is only black and white. I have a code like this:
int count = 0;
for ( int j = 0; j < Image.rows; j ++ )
{
for ( int i = 0; i < Image.cols; i ++ )
{
if ( Image.at<int>(i,j) >= 150 )
{
count ++ ;
}
}
}
For some reason, the above code doesn't work, it just stops reacting. I checked, and the line" if ( Image.at(i,j) >= 150 ) " causes the problem. My "Image" is a "cv::Mat", with "CV_8UC3" type. Is there someone can help me? Thank you.
In addition to my comment to Robin's answer, your error is that you try to access an image of CV_8UC3 type as ints. If you want to check grey levels, do something like this (note the "unsigned char" instead of "int", as in Robin's answer).
cv::Mat greyscale;
cv::cvtColor(image,grayscale,CV_RGB2GRAY);
// either, most elegant:
int count = cv::countNonZero(greyscale >= 150);
// or, copied from Robin's answer:
int count = 0;
for(int i = 0; i < greyscale.rows; ++i) {
const unsigned char* row = greyscale.ptr<unsigned char>(i);
for(int j = 0; j < greyscale.cols; j++) {
if (row[j] >= 150)
++count;
}
}
I believe this is much neater:
Mat result;
threshold(Image,result,150,255,THRESH_BINARY);
int white_count = countNonZero(result);
Write Image.at<unsigned char>(j,i) not Image.at<unsigned char>(i,j) if you are using i for cols and j for rows.
I think you have to access the row before the column, meaning you should swap i and j.
Substitute if ( Image.at<int>(i,j) >= 150 ) with if ( Image.at<int>(j,i) >= 150 )
There are easier ways to access a Mat though.
OpenCV provides an STL-like iterator which is easy to use and if you want to access all the elements very easy to use. Example:
int count = 0;
MatConstIterator_<int> it = Image.begin<int>(), it_end = Image.end<int>();
for(; it != it_end; ++it)
if ((*it) >= 150)
++count;
Last but not least you could also get a pointer to each row and access the data via the plain [] operator:
int count = 0;
for(int i = 0; i < Image.rows; ++i) {
const int* Ii = Image.ptr<int>(i);
for(int j = 0; j < Image.cols; j++) {
if (Ii[j] >= 150)
++count;
}
}
you could access the CV_8UC3 Pixels with opencv bytes vectors (unsigned char pixels) !
In this case you can make the following (now you could also use some special color threshold)
int channel = 0;
Image.at<Vec3b>( row , col )[channel]
There are a lot of methods to access the cv::Mat image,
if you want to directly access the color image(CV_8UC3),
it could be implemented by following:
int count = 0;
int threshold = 150;
for(int j = 0; j < img.rows; j++) {
for(int i = 0; i < img.cols; i++) {
//white point which means that the point in every channel(BGR)
//are all higher than threshold!
if(img.ptr<cv::Vec3b>(j)[i][0] > threshold &&
img.ptr<cv::Vec3b>(j)[i][1] > threshold
img.ptr<cv::Vec3b>(j)[i][2] > threshold ) {
count++;
}
}
}
but I recommend that if you only want to count white points, you can just convert image into grayscale
(CV_8UC1), and do as following:
cv::Mat img;
cv::cvtColor(src,img,CV_BGR2RGB);
int count = 0;
int threshold = 150;
for(int j = 0; j < img.rows; j++) {
for(int i = 0; i < img.cols; i++) {
if(img.ptr<uchar>(j)[i] > threshold) {
count++;
}
}
}
Finally, note that access cv::Mat image by img.ptr< Imagetype> will not check the accessed point is correct, so if you certainly know the range of image, the access image by ptr will be fine, otherwise, you can do by img.at< Imagetype>(), it will check every point is correct at every call,why access image by ptr is faster
so if there are invalid accessed point, it will assert you!