s it possible to:
read an image given by just a filename (not knowing the image format) to a 2d matrix rgb uncompressed form (e.g. read an JPG to a 2d array)
access the bytes of that image, copy them, change them... (e.g. inverse the colors, I need a pointer to the image bytes, setters/getters won't do )
rgb8_image_t img;
jpeg_read_image ("lena.jpg",img);
i use these to load the image. now how do i access the pixels or bytes of this image?
Here is a sample that sets G component of all pixels to 128
rgb8_image_t img;
const rgb8_view_t & mViewer = view(img);
for (int y = 0; y < mViewer.height; ++y)
{
rgb8_view_t::x_iterator trIt = mViewer.row_begin(y);
for (int x = 0; x < mViewer.width; ++x)
at_c<1>(trIt[x]) = 128;
}
Related
I'm trying to change the brightness of an image by coverting it from BGR to LAB and changing the L parameter to L+brightness. It works to change the brightness but the output image is blue , why?
void MainWindow::BrightnessSlider(cv::Mat image)
{
cv::Mat image2;
cv::cvtColor(image,image2,cv::COLOR_BGR2Lab);
for (int i=0; i < image2.rows; i++)
{
for (int j=0; j < image2.cols; j++)
{
image2.at<cv::Vec3b>(i,j)[0] = cv::saturate_cast<uchar>(image2.at<cv::Vec3b>(i,j)[0] + brightness);
}
}
cv::cvtColor(image2,image2,cv::COLOR_Lab2BGR);
QImage imageupdate= QImage((const unsigned char*)(image2.data), image2.cols,image2.rows,QImage::Format_RGB888);
int w = ui->label->width();
int h =ui-> label->height();
ui->label->setPixmap(QPixmap::fromImage(imageupdate.scaled(w,h,Qt::KeepAspectRatio)));
}
The main problem here is that 3-channel color images in OpenCV use BGR memory layout, while in Qt they use RGB memory layout. That's why your image shown in QLabel looks "blue".
To fix the memory layout problem, you should change cv::COLOR_Lab2BGR to cv::COLOR_Lab2RGB in the second cv::cvtColor():
cv::cvtColor(image2, image2, cv::COLOR_Lab2RGB);
Or append .rgbSwapped() to imageupdate (note that imageupdate will not share memory block with image2):
QImage imageupdate = QImage((const unsigned char*)(image2.data),
image2.cols, image2.rows, QImage::Format_RGB888).rgbSwapped();
BTW, you can just use Mat::operator+(const Scalar&) to change the value for all pixels, the color conversion and for-loops are unnecessary:
cv::Mat image2 = image + cv::Scalar::all(brightness);
// convert BGR to RGB if you don't want to allocate additional memory
// for imageupdate with QImage::rgbSwapped():
cv::cvtColor(image2, image2, cv::COLOR_BGR2RGB);
so i'm making this project where i'm making the reflection of an image on OpenCV (without using the flip function), and the only problem (i think) to finish it, is that the image that is suppose to come out reflected, is coming out as all blue.
The code i have (i took out the usual part, the problem should be around here):
Mat imageReflectionFinal = Mat::zeros(Size(220,220),CV_8UC3);
for(unsigned int r=0; r<221; r++)
for(unsigned int c=0; c<221; c++) {
Vec3b intensity = image.at<Vec3b>(r,c);
imageReflectionFinal.at<Vec3b>(r,c) = (uchar)(c, -r + (220)/2);
}
///displays images
imshow( "Original Image", image );
imshow("Reflected Image", imageReflectionFinal);
waitKey(0);
return 0;
}
There are some problems with your code. As pointed out, your iteration variables go beyond the actual image dimensions. Do not use hardcoded bounds, you can use inputImage.cols and inputImage.rows instead to obtain the image dimensions.
There’s the variable (a BGR Vec3b) that is set but not used - Vec3b intensity = image.at<Vec3b>(r,c);
Most importantly, it is not clear what you are trying to achieve. The line (uchar)(c, -r + (220)/2); does not give out much info. Also, which direction are you flipping the original image around? X or Y axis?
Here’s a possible solution to flip your image in the X direction:
//get input image:
cv::Mat testMat = cv::imread( "lena.png" );
//Get the input image size:
int matCols = testMat.cols;
int matRows = testMat.rows;
//prepare the output image:
cv::Mat imageReflectionFinal = cv::Mat::zeros( testMat.size(), testMat.type() );
//the image will be flipped around the x axis, so the "target"
//row will start at the last row of the input image:
int targetRow = matRows-1;
//loop thru the original image, getting the current pixel value:
for( int r = 0; r < matRows; r++ ){
for( int c = 0; c < matCols; c++ ) {
//get the source pixel:
cv::Vec3b sourcePixel = testMat.at<cv::Vec3b>( r , c );
//source and target columns are the same:
int targetCol = c;
//set the target pixel
imageReflectionFinal.at<cv::Vec3b>( targetRow , targetCol ) = sourcePixel;
}
//for every iterated source row, decrease the number of
//target rows, as we are flipping the pixels in the x dimension:
targetRow--;
}
Result:
I know Mat data save each pixel data(RGB data in a column) as a unsigned char. And texture data in unity3d is byte[]. I try to do the following thing, but the result is not right, the image capture from the camera displayed in the hwind is not right.
Mat src_frame;//this is every frame that captured from the current camera
D3DLOCKED_RECT d3d_rect;
byte *pSrc = src_frame.data;
byte *pDest = (byte *)d3d_rect.pBits;
int stride = d3d_rect.Pitch;
int pixel_w_size = src_frame.cols;
for (unsigned long i = 0; i < src_frame.rows; i++){
memcpy(pDest, pSrc, pixel_w_size);
pDest += stride;
pSrc += pixel_w_size;
}
Only gray image shows, I don't know why this happens. Does the Mat data sequence is different from the texture data? Their data both contain the RGB information.
pixel_w_size should be src_frame.cols multiplied with the bytes per pixel (3 in case of RGB) or even better use elemSize().
So use:
int pixel_w_size = src_frame.cols * src_frame.elemSize();
I am a newbie to c++. I am using it for image processing. My basic idea is to load an image and store the pixel values or intensities into a matrix or an array, so that i can perform further manipulations on them.
So, what i have done so far is
QPixmap pixmap("lena.bmp");
pixmap = pixmap.copy(512,512,128,128);
pixmap = pixmap.scaled(32,32);
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++)
{
col = image.pixel(i,j);
g = qGray(col);
image.setPixel(i,j,qRgb(g,g,g));
m(i,j) = (image.pixel(i,j));
}
}
for instance here i use Qpixmap in Qt for reading image and use boost to generate a matrix with the data.
But is there any other simpler way to read the image and to store it in a matrix? and perform manipulations and then display the new manipulated matrix as an image?
You could use OpenCV library, where images are by default represented as matrixes. OpenCV is very popular for image manipulation, and has many features. You can grab an example of loading image to matrix in OpenCV here: http://docs.opencv.org/doc/tutorials/introduction/display_image/display_image.html
I am looking for a way to take an image and get masks of all objects in it by color. My goal is to be able to separate similarly colored objects into layers so I can further examine each layer. The plan is to use each mask against the original image to create a histogram of the colors in each object and determine the similarity with other objects in the image. If something is similar enough it will be combined with other objects to form a layer.
The problem is that I can not find a function in opencv to find all objects in an image based on color contiguity. I am sure such an algorithm exists, but it seems to be evading me. Does anyone know of an algorithm or function like this?
The best method that I have found is K-means Clustering. This separates the image into different layers based on color. It uses a k-neighbors algorithm to do so. With this I am able to effectively split the image into several layers that are of similar color.
#define numClusters 7
cv::Mat src = cv::imread("img0.png");
cv::Mat kMeansSrc(src.rows * src.cols, 3, CV_32F);
//resize the image to src.rows*src.cols x 3
//cv::kmeans expects an image that is in rows with 3 channel columns
//this rearranges the image into (rows * columns, numChannels)
for( int y = 0; y < src.rows; y++ )
{
for( int x = 0; x < src.cols; x++ )
{
for( int z = 0; z < 3; z++)
kMeansSrc.at<float>(y + x*src.rows, z) = src.at<Vec3b>(y,x)[z];
}
}
cv::Mat labels;
cv::Mat centers;
int attempts = 2;
//perform kmeans on kMeansSrc where numClusters is defined previously as 7
//end either when desired accuracy is met or the maximum number of iterations is reached
cv::kmeans(kMeansSrc, numClusters, labels, cv::TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 8, 1), attempts, KMEANS_PP_CENTERS, centers );
//create an array of numClusters colors
int colors[numClusters];
for(int i = 0; i < numClusters; i++) {
colors[i] = 255/(i+1);
}
std::vector<cv::Mat> layers;
for(int i = 0; i < numClusters; i++)
{
layers.push_back(cv::Mat::zeros(src.rows,src.cols,CV_32F));
}
//use the labels to draw the layers
//using the array of colors, draw the pixels onto each label image
for( int y = 0; y < src.rows; y++ )
{
for( int x = 0; x < src.cols; x++ )
{
int cluster_idx = labels.at<int>(y + x*src.rows,0);
layers[cluster_idx].at<float>(y, x) = (float)(colors[cluster_idx]);;
}
}
std::vector<cv::Mat> srcLayers;
//each layer to mask a portion of the original image
//this leaves us with sections of similar color from the original image
for(int i = 0; i < numClusters; i++)
{
layers[i].convertTo(layers[i], CV_8UC1);
srcLayers.push_back(cv::Mat());
src.copyTo(srcLayers[i], layers[i]);
}
I suggest you convert the image to the HSV-space (Hue-Saturation-Value). Then make a histogram based on the Hue value to find thresholds online, or define them before (depends if this is a general problem or a given one).
Crate one-channel images for each layer you want to form. (set them as black)
Then then use the HSV-image and mark a layer based on the threshold values. You might want to add some constant thresholds for value and saturation too (to avoid dark and light areas)
Does this make sense to you?
I think that you should proceed in the following proceess:
Smooth you image if it has too much details.
find edges
Find all contours
Try to find the color of each contour..lets say you want to keep all contours which are red. So, keep only those contours which are red.
Once you find the contours which you want to keep, then create a mask image based upon the contours you want to keep.
Using mask image, extract the required objects from the original image.