Increment the value of each pixel of an image - c++

I have an image. I want to modify the image in such a way that the value of each pixel is increased by a particular margin. Next I want to save the newly created image and display it.
I tried changing each pixel value but was only able to set it to constant value. I don't want all the pixels to be constant but their value should increase by (lets say) 50.
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat image;
image = imread("/home/rohit_136/Desktop/image.jpg",CV_LOAD_IMAGE_UNCHANGED);
for (int i = 0; i < image.cols; i++) {
for (int j = 0; j < image.rows; j++) {
Vec3b intensity = image.at<Vec3b>(j, i)=50
}
}
return 0;
}

Vec3b is a vector which contains 3 bytes (chars). Each byte denotes the value of an individual BGR (blue, green, red) or RGB channel. You should traverse this vector and modify each channel independently. Be careful, because we are talking about bytes, each byte should take a value between 0 and 255. I suggest setting a threshold for avoiding overflow.
Note: if you don't care about alpha channel, I suggest loading your image with CV_LOAD_IMAGE_COLOR. This will ensure that your image is loaded in the BGR format.

cv::Mat Image =cv::imread("image.jpg");
uint8_t * orig_ptr = (uint8_t*)Image.data;
for (int y = 0; y < Image.rows; y++)
{
for (int x = 0; x < Image.cols; x++)
{
/*Reading Pizel Values*/
int R = orig_ptr[x * 3 + y*Image.step + 2];/*R -Pixel*/
int G = orig_ptr[x * 3 + y*Image.step + 1];/*G-Pixel*/
int B = orig_ptr[x * 3 + y*Image.step]; /*B-Pixel*/
/*Updating Values*/
orig_ptr[x * 3 + y*Image.step + 2] = cv::saturate_cast<uint8_t>(R + 50);
orig_ptr[x * 3 + y*Image.step + 1] =cv::saturate_cast<uint8_t>(G + 50);
orig_ptr[x * 3 + y*Image.step]=cv::saturate_cast<uint8_t>(B + 50);
}
}

Related

opencv slicing of a vector Mat

I am new with OpenCV. I am working on Visual Studio 2017 and use the plugin Image Watch to see Mat file of openCV.
What I've done:
I have to read a binary file to get 1000 images (256*320 pixels uint16 so 2 octets by pixel) in an array of double. After this, I wanted to see with Image Watch my data to be sure all is okay. So I convert the first image into a uchar on 8 bit to visualise it. I add my code (most part don't read it, just go to the end) :
#include "stdafx.h"
#include <iostream>
#include "stdio.h"
#include <fstream>
#include <stdint.h>
#include "windows.h"
#include <opencv2/core/core.hpp> // cv::Mat
#include <math.h>
#include <vector>
using namespace std;
using namespace cv;
template<class T>
T my_ntoh_little(unsigned char* buf) {
const auto s = sizeof(T);
T value = 0;
for (unsigned i = 0; i < s; i++)
value |= buf[i] << CHAR_BIT * i;
return value;
}
int main()
{
ifstream is("Filename", ifstream::binary);
if (is) {
// Reading size of the file and initialising variables
is.seekg(0, is.end);
int length = is.tellg();
int main_header_size = 3000;
int frame_header_size = 1000;
int width = 320, height = 256, count_frames = 1000;
int buffer_image = width * height * 2;
unsigned char *data_char = new unsigned char[length]; // Variable which will contains all the data
// Initializing 3D array for stocking all images
double ***data;
data = new double**[count_frames];
for (unsigned i = 0; i < count_frames; i++) {
data[i] = new double*[height];
for (unsigned j = 0; j < height; j++)
data[i][j] = new double[width];
}
// Reading the file once
is.seekg(0, is.beg);
is.read(reinterpret_cast<char*>(data_char), length);
// Convert pixel by pixel uchar into uint16 (using pointer on data_char)
int indice, minid = 65536.0, maxid = 0.0;
for (unsigned count = 0; count < count_frames; count++) {
// Initialize pointer address
indice = main_header_size + count * (frame_header_size + buffer_image) + frame_header_size;
for (unsigned i = 0; i < height; i++) {
for (unsigned j = 0; j < width; j++) {
data[count][i][j] = my_ntoh_little<uint16_t>(data_char + indice);
// Search for min/max for normalize after
if (data[count][i][j] < minid and count == 0)
minid = data[count][i][j];
if (data[count][i][j] > maxid and count == 0)
maxid = data[count][i][j];
// Updating pointer to next pixel
indice += 2;
}
}
}
// Get back first image, normalize between 0-255, cast into uchar to the future Mat object
uchar *dataImRGB = new uchar[width * height * 3];
int image_display = 900;
int pixel_norm;
for (unsigned i = 0; i < height; i++) {
for (unsigned j = 0; j < width; j++) {
pixel_norm = round((data[image_display][i][j] - double(minid)) / double(maxid - minid) * 255);
dataImRGB[i * 320 * 3 + 3 * j] = static_cast<uchar>(pixel_norm);
dataImRGB[i * 320 * 3 + 3 * j + 1] = static_cast<uchar>(pixel_norm);
dataImRGB[i * 320 * 3 + 3 * j + 2] = static_cast<uchar>(pixel_norm);
}
}
// Create Mat object (it is imageRGB8 I can see on Image watch)
Mat imageRGB8 = Mat(width, height, CV_8UC3, dataImRGB);
// Creating a list of Map and add first Mat
vector<Mat> listImages;
listImages.push_back(imageRGB8);
// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
// Future : directly keep the uchar read in the original file and import it on a Mat object
// But how to get the pixel at (0,0) of the first Mat on the vector ?
// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
// De-Allocate memory to prevent memory leak
for (int i = 0; i < count_frames; ++i) {
for (int j = 0; j < height; ++j)
delete[] data[i][j];
delete[] data[i];
}
delete[] data;
}
return 0;
}
Where I am stuck:
I don't know how to work with this vector, how to manipulate the data. For example, if i want to do the mean of all images, so the mean of all Mat objects in the vector, how to do this ? Or just how to get the first pixel of the third image in the vector ? These examples have for aim to explain me the slicing with such type of data because I know how it works with vector of double, but not with openCv object.
Thank you in advance for any help/advice.
Assuming that you have got all of your images properly packed into your image list you can do the following:
This will get the mean of all images in your list:
cv::Scalar meansum(0.0f,0.0f,0.0f);
size_t length = listImages.size();
for (size_t i = 0; i < length; i++){
//mu == mean of current image
cv::Scalar mu = cv::mean(listImages[i]);
meansum += mu;
}
float means[3] = { meansum[0] / length, meansum[1] / length, meansum[2] / length };
std::cout << "Means " << means[0] << " " << means[1] << " " << means[2] << std::endl;
To get the first pixel in your third image you can use the at() method or a row pointer. (Row pointers are faster, but don't have any guards against accessing out of bounds memory locations.)
Mat third_image = list_images[2];
//using at()
uchar first_pixel_blue_value = third_image.at<uchar>(0,0,0);
std::cout<<(int)first_pixel_blue_value<<std::endl;
//using row pointer
uchar* row = third_image.ptr<uchar>(0); //pointer to row 0
std::cout<<"blue: " <<(int)row[0];
std::cout<<" green: "<<(int)row[1];
std::cout<<" red: " <<(int)row[2];
More info can be found here:
https://docs.opencv.org/3.1.0/d2/de8/group__core__array.html (under functions)
and here:
https://docs.opencv.org/trunk/d3/d63/classcv_1_1Mat.html

opencv::Mat, get pixel value from the raw data?

I have an image, as a cv::Mat. I am getting the raw data from this, with:
uchar* data = (uchar *)pImg.data;
I need to pass this data to a function, then cycle through each pixel of the image. I would have done:
for (int i = 0; i < image.rows; ++i)
{
for (int j = 0; j < image.cols; ++j)
{
//pixel = cv::Point(i,j);
}
}
What is the equivalent of this, using the uchar* data?
It is pretty easy but you need to remember one thing, this image.elemSize() indicates how many bytes there are per pixel (this function is taken from OpenCV mat). So this loop will look little bit different for different image formats. There is a example inside the loop
for (auto i = 0; i < image.rows * image.cols; i+=image.elemSize())
{
//for CV_8UC1
//auto pixel = *(image.data + i)
//for RGB as CV_8UC3
auto r = *(image.data + i)
auto g = *(image.data + i + 1)
auto b = *(image.data + i + 2)
}
The correct pixel value can be accessed from the raw data provided the following parameters are known:
X coordinate of pixel ( column number )
Y coordinate of pixel ( row number )
Image depth (actual data type of a single pixel i.e. uchar, ushort, float etc)
Number of channels of the image
Image step in bytes
Given the above information, the pixel can be accessed as follows (for CV_8UC3 type):
uchar* data = (uchar *)pImg.data;
for (int i = 0; i < image.rows; ++i)
{
for (int j = 0; j < image.cols; ++j)
{
uchar b = data[i * pImg.step + pImg.channels() * j + 0];
uchar g = data[i * pImg.step + pImg.channels() * j + 1];
uchar r = data[i * pImg.step + pImg.channels() * j + 2];
}
}

Prewitt filter, edge detection

I have this code that implements Prewitt edge detection. What I need to do is to implement it with only one buffer, meaning, I will not create copy of the image but edit original image. So if i want to change pixel with value 78, I cant put the new value e.g. 100 until all surrounding pixels have read value 78. Color values of the pixels. I have tried all day to figure it out but couldn't, if someone would write me some kind of pseudocode I would be very grateful
void filter_serial_prewitt(int *inBuffer, int *outBuffer, int width, int height){
for (int i = 1; i < width - 1; i ++) {
for (int j = 1; j < height - 1; j ++) {
int Fx = 0;
int Fy = 0;
int F = 0;
for (int m = -1; m <= 1; m++) {
for (int n = -1; n <= 1; n++) {
Fx += inBuffer[(j + n) * width + (i + m)] * n;
Fy += inBuffer[(j + n) * width + (i + m)] * m;
}
}
F = abs(Fx) + abs(Fy);
if (F < THRESHOLD){
outBuffer[j * width + i] = 255;
} else{
outBuffer[j * width + i] = 0;
}
}
}
}
One thing to know about a Prewitt operator is that it is separable. See the Wikipedia article for details.
To calculate a single output row, you need to do the following (pseudocode):
int* buffer = malloc (sizeof(int) * width);
for (int i = 0; i < width; i++)
{
// Do the vertical pass of the convolution of the first 3 rows into
// the buffer.
buffer [ i ] = vertical_convolve(inBuffer [ i ], vertical_kernel);
}
// Next, do the horizontal convolution of the first row. We need to
// keep the previous value in a temp buffer while we work
int temp0 = horizontal_convolve(buffer [ 0 ], horizontal_kernel);
for (int i = 1; i < width; i++)
{
int temp1 = horizontal_convolve(buffer[ i ], horizontal_kernel);
inBuffer [ i - 1 ] = temp0;
temp0 = temp1;
}
That requires a buffer that is 1 pixel tall and the width of the image.
To work on the whole image, you need to keep 2 of the above buffers around and after you calculate a pixel on the third line, you can replace the first pixel of the first line of the image with the first pixel of the first buffer. Then you can put the newly calculated value into the buffer.
So in this scenario, you won't keep around an entire second image, but will need to keep around 2 1-pixel tall buffers that are as wide as the image.

C++ Stretching an equalized image

From an (2)equalized image I have to create a (3).
Original image: http://i.imgur.com/X5MKF6z.jpg
Equalized image : http://i.imgur.com/oFBVUJp.png
Equalized and Stretch image: http://i.imgur.com/V7jeaRQ.png
With OpenCV I could have used equalizeHist() that does both equalization and stretching.
So without using OPENCV, how can I do stretching from an equalization image. The equalization part is done below.
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv/highgui.h>
#include <cstring>
using std::cout;
using std::cin;
using std::endl;
using namespace cv;
void imhist(Mat image, int histogram[])
{
// initialize all intensity values to 0
for (int i = 0; i < 256; i++)
{
histogram[i] = 0;
}
// calculate the no of pixels for each intensity values
for (int y = 0; y < image.rows; y++)
for (int x = 0; x < image.cols; x++)
histogram[(int)image.at<uchar>(y, x)]++;
}
void cumhist(int histogram[], int cumhistogram[])
{
cumhistogram[0] = histogram[0];
for (int i = 1; i < 256; i++)
{
cumhistogram[i] = histogram[i] + cumhistogram[i - 1];
}
}
int main()
{
// Load the image
Mat image = imread("y1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
// Generate the histogram
int histogram[256];
imhist(image, histogram);
// Caluculate the size of image
int size = image.rows * image.cols;
float alpha = 255.0 / size;
// Calculate the probability of each intensity
float PrRk[256];
for (int i = 0; i < 256; i++)
{
PrRk[i] = (double)histogram[i] / size;
}
// Generate cumulative frequency histogram
int cumhistogram[256];
cumhist(histogram, cumhistogram);
// Scale the histogram
int Sk[256];
for (int i = 0; i < 256; i++)
{
Sk[i] = cvRound((double)cumhistogram[i] * alpha);
}
// Generate the equlized image
Mat new_image = image.clone();
for (int y = 0; y < image.rows; y++)
for (int x = 0; x < image.cols; x++)
new_image.at<uchar>(y, x) = saturate_cast<uchar>(Sk[image.at<uchar>(y, x)]);
//////////////////////////////////////////
// // Generate the histogram stretched image
Mat str_image = new_image.clone();
//for (int a = 0; a < str_image.rows; a++)
// for (int b = 0; b < str_image.cols; b++)
// Display the original Image
namedWindow("Original Image");
imshow("Original Image", image);
// Display equilized image
namedWindow("Equalized Image");
imshow("Equalized Image", new_image);
waitKey();
return 0;
}
The normal way to do this is to find your darkest pixel, and your brightest. You can do this in a singe loop iterating over all your pixels, pseudo-code like this:
darkest=pixel[0,0] // assume first pixel is darkest for now, and overwrite later
brightest=pixel[0,0] // assume first pixel is lightest for now, and overwrite later
for all pixels
if this pixel < darkest
darkest = this pixel
else if this pixel > brightest
brightest = this pixel
endif
end for
Simple enough. So, let's say the darkest and brightest are 80 and 220 respectively. Now you need to stretch this range 80..220 onto the full range 0..255.
So you subtract 80 from every pixel in your image to shift down to zero at the left end of the histogram, so your range is now 0..140. So now you need to multiply every pixel by 255/140 to stretch the right end out to 255. Of course, you can do both pieces of arithmetic in a single pass over your pixel array.
for all pixels
newvalue = int((current value - darkest)*255/(brightest-darkest))
end for

How to load nearby pixels using pointer

Suppose i have an image matrix and i am at a particular pixel [say 4] like this:
0 1 2
3 `4` 5
6 7 8
I am trying to cycle through all pixels and am attempting to access 0,1,2, 3,5 6,7,8 whose values i am storing in the array called Pixel.... here is my attempt at it using OpenCV, kindly tell me where am i going wrong.
I am using pointer temp_ptr to access the IplImage image.
uchar* temp_ptr=0 ;
CvScalar Pixel[3][3];
int rows=image->height,cols=image->width,row,col;
for( row = 0; row < rows-2; ++row)
{
for ( col = 0; col < cols-2; ++col)
{
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row)))[col*3];
for (int krow = -1 ; krow <= 1; krow++)
{
for (int kcol = -1; kcol <= 1; kcol++)
{
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row+krow)))[(col+kcol)*3];
for(int i=0; i < 3; i++)
{
for(int j=0; j < 3; j++)
{
for(int k=0; k < 3; k++)
{
Pixel[i][j].val[k]=temp_ptr[k];
}
}
}
}
}
}
}
I am not really sure how to load the sorrounding Pixels usingtemp_ptr, please help me out.
Well sir, it sounds like you want to do convolution, and doing it this way when you have OpenCV at your fingertips is a bit like hammering a can opener on your Spaghettios to burst it open by blunt force.
In fact, what you're doing is almost exactly the output of cv::blur(src, dst, cv::Size(3,3)) except it also includes the center pixel in the average.
If you want to exclude the center pixel then you can create a custom kernel - just a matrix with appropriate weights:
[.125 .125 .125
.125 0 .125
.125 .125 .125 ]
and apply this to the image with cv::filter2d(src, dst, -1, kernel).
Assuming image->imageData is in RGB format, so there are 3 bytes for each pixel, you could do something like this:
int rows = image->height;
int cols = image->width;
uchar* temp_ptr = 0;
CvScalar pixels[8];
for (int col = 0; col < image->height - 2; col++) {
temp_ptr = image->imageData + image->width * col + 1;
for (int row = 0; row < image->width - 2; row++) {
temp_ptr += row * 3;
pixels[0].val = temp_ptr - width * 3 - 3; // pixel 0 from your example
pixels[1].val = temp_ptr - width * 3; // 1
pixels[2].val = temp_ptr - width * 3 + 3; // 2
pixels[3].val = temp_ptr - 3; // 4
pixels[4].val = temp_ptr + 3; // etc...
pixels[5].val = temp_ptr + width * 3 - 3;
pixels[6].val = temp_ptr + width * 3;
pixels[7].val = temp_ptr + width * 3 + 3;
// calculate averages here and store them somewhere (in a vector perhaps)
}
}
Note I didn't test this code.
First of all you have to start learning some programming. Your complete code is a mess.
Some major problems I could quickly found:
First of all you have to start your first two for loops from 1 (because you decrement by -1 when you apply the window) and you will end up reading some memory address that are not allocated.
Second the first temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row)))[col*3] is useless so you can remove it.
the other
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row+krow)))[(col+kcol)*3];
is having a small problem, the operator precedence, should be:
temp_ptr = &((uchar*)(image->imageData + image->widthStep*(row+krow))[(col+kcol)*3];
you don't need the other 3 inside loops
Also is not clear what you want to do, you want to get the neighborhood of a specific pixel (then you need no loops) or you want to apply a kernel to each pixel from the image.