I'm new to openCV and C++. I would like to change the pixel values of an image I loaded and display that new image in another window to compare the results (just visually). However, when I run the code, I get two original images. This means that either my for loop isn't doing what's it suppose to do (which i doubt since it makes sense to me) or the pixel value is lost and is not being saved to show the new image. I read a previous post that said I should include this statement after working with each pixel to set in to the altered image. The statement is: img.at(Point(x,y)) = color.
Could somebody please tell me what I'm doing wrong?
Thank you
cv::Mat img = cv::imread("12.jpg", CV_LOAD_IMAGE_COLOR);
// start of pixel navigation
Mat navigateImage(Mat) {
for(int x = 0; x > img.rows; x++)
{
for(int y = 0; y > img.cols; y++){
Vec3b color = img.at<Vec3b>(Point(x,y));
if ( color[0] > 10 && color [1] > 10 && color[2]> 10 )
{
color[0] = 0 ;
color[1] = 0;
color[2] = 0;
img.at<Vec3b>(Point(x,y)) = color;
}
else
{
color.val[0] = 255 ;
color.val[1] = 255;
color.val[2] = 255;
img.at<Vec3b>(Point(x,y)) = color;
}
}
}
return img;
}
// end of pixel navigation
int main( int argc, char** argv )
{
if(! img.data){
cout << "could not open or find the image" << endl;
return -1;}
Mat newImage = navigateImage(img);
cv::imshow( " Original", img);
cv::imshow( " Altered ", newImage);
cv::waitKey(0);
return 0;
}
(1). Firstly,
for(int x = 0; x > img.rows; x++)
and
for(int y = 0; y > img.cols; y++)
should be
for(int x = 0; x < img.cols; x++)
and
for(int y = 0; y < img.rows; y++)
respectively.
Since, you never enter the loop because of this mistake, both images are same.
(2). Secondly,
Mat navigateImage(Mat)
should be
Mat navigateImage(Mat img)
(3). Thirdly, put
cv::Mat img = cv::imread("12.jpg", CV_LOAD_IMAGE_COLOR);
in main function.
(4). Lastly,
replace,
Mat newImage = navigateImage();
by
Mat newImage = navigateImage(img.clone());
else, both images will be same.
CORRECTED CODE -
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
// start of pixel navigation
Mat navigateImage(Mat img) {
for(int x = 0; x < img.cols; x++)
{
for(int y = 0; y < img.rows; y++){
Vec3b color = img.at<Vec3b>(Point(x,y));
if ( color[0] > 10 && color [1] > 10 && color[2]> 10 )
{
color[0] = 0 ;
color[1] = 0;
color[2] = 0;
img.at<Vec3b>(Point(x,y)) = color;
}
else
{
color.val[0] = 255 ;
color.val[1] = 255;
color.val[2] = 255;
img.at<Vec3b>(Point(x,y)) = color;
}
}
}
return img;
}
// end of pixel navigation
int main( int argc, char** argv )
{
Mat img = cv::imread("12.png", CV_LOAD_IMAGE_COLOR);
if(! img.data){
cout << "could not open or find the image" << endl;
return -1;
}
Mat newImage = navigateImage(img.clone());
cv::imshow( " Original", img);
cv::imshow( " Altered ", newImage);
cv::waitKey(0);
return 0;
}
Related
I've got a problem with creating a trackbar which would adjust brightness of the displayed picture.
This is my code (part which is involved with brightness):
int brightness_value = 25; //global values
const int max_value = 255;
int main()
{
Mat brightImage;
srcImage.copyTo(brightImage);
namedWindow("Bright Image");
moveWindow("Bright Image", 300, 600);
createTrackbar("Brightness", "Bright Image", &brightness_value, max_value);
for (int i = 0; i < brightImage.rows; i++)
{
for (int j = 0; j < brightImage.cols; j++)
{
Vec3b pixelColor;
pixelColor = brightImage.at<Vec3b>(Point(j, i));
for (int k = 0; k < 3; k++) //vector with 3 byte entries
{
if (pixelColor[k] + getTrackbarPos("Brightness", "Bright Image") > 255)
pixelColor[k] = 255;
else
pixelColor[k] += getTrackbarPos("Brightness", "Bright Image");
brightImage.at<Vec3b>(Point(j, i)) = pixelColor;
}
}
}
imshow("Bright Image", brightImage);
waitKey(0);
return 0;
}
This way the brightness of the image is adjusted only once, when the program starts. But when I want to change it with the trackbar nothing happens. Where is the problem, how should I do it so the brightness will change every time I move the trackbar?
Thanks for any help :)
And that's the result: (on the left original image, on the right with changed brightness)
createTrackbar takes a pointer to callback function which is called when position of trackbar is being changed. In this callback you should redrawn your image with changed brightness level and refresh window by imshow. Such callback takes a pointer to void data - it enables you to pass any data you want to use when redrawing your image, in this case it should be pointer to output image (and probably a pointer to source image - you should always add new brightness level to original image, not modified one):
struct Params {
cv::Mat* src;
cv::Mat* dest;
};
void makeBrightness(int pos, void* data) {
Params* params = (Params*)data;
for (int i = 0; i < params->src->rows; i++) {
for (int j = 0; j < params->src->cols; j++) {
Vec3b pixelColor;
pixelColor = params->src->at<Vec3b>(Point(j, i));
for (int k = 0; k < 3; k++) {
if (pixelColor[k] + pos > 255)
pixelColor[k] = 255;
else
pixelColor[k] += pos;
params->dest->at<Vec3b>(Point(j, i)) = pixelColor;
}
}
}
imshow("Bright Image", *(params->dest));
}
int main()
{
int brightness_value = 25; //global values
const int max_value = 255;
Mat srcImage = cv::imread("D:/lena.jpg");
Mat brightImage;
srcImage.copyTo(brightImage);
namedWindow("Bright Image");
moveWindow("Bright Image", 300, 600);
Params params;
params.src = &srcImage;
params.dest = &brightImage;
createTrackbar("Brightness", "Bright Image", &brightness_value, max_value, makeBrightness, ¶ms);
makeBrightness(brightness_value, ¶ms); // for first painting your image
waitKey(0);
return 0;
I am wanting to move through an image and take a 5x5 grid centered around each pixel in the image. I then want to sum that grid and compare it to a threshold.
int main()
{
Mat element = getStructuringElement(MORPH_RECT, Size(7, 7));
Mat im = imread("blob.png", IMREAD_GRAYSCALE);
bool fromCenter = false;
namedWindow("Crop frame", WINDOW_NORMAL);
Rect2d r = selectROI("Crop frame", im, fromCenter);
im = im(r);
erode(im, im, element);
Mat clone = im;
int sectionSize = 4;
int width = im.cols - sectionSize/2;
int height = im.rows - sectionSize/2;
int sum = 0;
int counter = 0;
for (int i = sectionSize/2; i < width; i++) {
for (int j = sectionSize/2; j < height; j++) {
Rect rect = Rect(i, j, sectionSize, sectionSize);
rect -= Point(rect.width / 2, rect.height / 2);
Mat temp = im(rect);
for (int x = 0; x < temp.cols; x++) {
for (int y = 0; y < temp.rows; y++) {
int pixelValue = (int)temp.at<uchar>(y, x);
sum += pixelValue;
}
}
cout << sum << endl;
if (sum > 3800) {
clone.at<uchar>(j, i) = 255;
}
else {
clone.at<uchar>(j, i) = 0;
}
namedWindow("erode", WINDOW_NORMAL);
imshow("erode", clone);
waitKey(1);
sum = 0;
}
}
}
I am getting fluctuations in the pixel sum based on where I select my ROI in the image even when both over white space Also, my pixel sum is changing when I change the value of the clone pixel in this section of the code which I do not understand at all:
if (sum > 3800) {
clone.at<uchar>(j, i) = 255;
}
else {
clone.at<uchar>(j, i) = 0;
}
I am trying to make an image black and white so i put threshold 100. all the values below 100 will be black and the rest will be white. So i go through every pixel and check its value if it below 100 then i change the value to 0 otherwise i change it to 255. but the code doesn't work. when i print the values of the image. all the value of the image became 225.
Image before run The input image and this is the image after runthe output
int main()
{
int x;
Mat img = imread("Canny.png");
cout << depthToStr(img.depth()) << endl;
img.convertTo(img, CV_32S);
// threshold 100.
for (int z = 0; z < img.rows; z++)
{
for (int y = 0; y < img.cols; y++)
{
if (img.at<int>(z,y) >= 100);
{
img.at<int>(z, y) = 225;
}
}
}
// Print the images.
for (int z = 0; z < img.rows; z++)
{
for (int y = 0; y < img.cols; y++)
{
cout << img.at<int>(z, y) << "\t";
}
cout << endl;
}
img.convertTo(img, CV_8U);
imshow(" ",img);
waitKey(0);
cin >> x;
waitKey(0);
return 0;
}
The if statement has a bug. Remove the semicolon at its end.
if( img.at<int>(z,y) >= 100 ){
img.at<int>(z, y) = 255;
}else{
img.at<int>(z, y) = 0;
}
Note that you most likely don't want to iterate over all pixels because it might not be well optimized for some processors. With opencv you can simply write
img = img > 100;
which would do the same as your cycle.
Another option is opencv function threshold
threshold(img, img, 100, 255, THRESH_BINARY)
I wants to embed watermark into an image using dct with c++ and opencv.
I split image into 8x8 block and apply dct to each block.
Now I don't know what to do next, Can anyone give me some hint or help me?
Here is my work so far.
int main() {
Mat originalImage;
originalImage = imread("image.jpg");
if( !originalImage.data )
{
std::cout<< "Error loading original image!"<<std::endl;
return -1;
}
cout << "Working on image from image.jpg" << endl;
/// Create Windows
namedWindow("Original", 1);
imshow( "Original", originalImage );
int x = 0; int y = 0;
moveWindow("Original", x, y);
imshow("Original", originalImage);
x += 100; y += 100;
int width = originalImage.size().width;
int height = originalImage.size().width;
cout << "Original image Width x Height is " << width << "x" << height << endl;
// Leave original alone, work on a copy
Mat dctImage = originalImage.clone();
// Step through the copied image with rectangles size 8x8
// For each block, split into planes, do dct, and merge back
// into the block. (This will affect the image from
// which the block is selected each time.)
for (int i = 0; i < height; i += 8)
{
for (int j = 0; j < width; j+= 8)
{
Mat block = dctImage(Rect(i, j, 8, 8));
vector<Mat> planes;
split(block, planes);
vector<Mat> outplanes(planes.size());
for (size_t k = 0; k < planes.size(); k++)
{
planes[k].convertTo(planes[k], CV_32FC1);
dct(planes[k], outplanes[k]);
outplanes[k].convertTo(outplanes[k], CV_8UC1);
}
merge(outplanes, block);
}
}
namedWindow("dctBlockImage");
moveWindow("dctBlockImage", x, y);
imshow("dctBlockImage", dctImage);
x += 100; y += 100;
waitKey();
destroyAllWindows();
return 0;
}
I wish to find number of white pixels in every row of binary image. And if that count is greater than 90, I wish to delete the entire row by changing each pixel value in that row to 0. The code that I wrote is not working. And apparently, I am getting the same binary image at output.
Please help me out in fixing the problem. BTW, am using openCV 2.0.
using namespace std;
double a = 15;
double b = 255;
Mat I1;
int main(int argv, char **argc)
{
cv: Mat I = imread("abc.bmp");
if (I.empty())
{
std::cout << "!!! Failed imread(): image not found" << std::endl;
}
threshold(I, I1, a, b, THRESH_BINARY);
int r = I.rows;
int c = I.cols;
for (int j = 0; j < r; j++)
{
int count = 0;
for (int i = 0; i < c; i++)
{
if (I1.at<uchar>(j, i) == 255)
count = count + 1;
}
if (count > 90)
{
for (int i = 0; i < c; i++)
I1.at<uchar>(j, i) = 0;
}
}
namedWindow("Display window", 0);// Create a window for display.
imshow("Display window", I1);
waitKey(0);
return 0;
}
By default imread returns 3 channel BGR image. If you want to load grayscale/binary image use cv::IMREAD_GRAYSCALE parameter:
cv::Mat I = cv::imread("abc.bmp", cv::IMREAD_GRAYSCALE);