Accessing random image pixels using a for loop

≡放荡痞女 提交于 2019-12-10 11:33:30

问题


I am trying to learn image processing using OpenCV. I wrote some code to edit an image. The edits are working well except for changing the color of some pixels.

I am trying to access some random pixels, and change their color (that is when status == 3). When I run the program I get "[run] Segmentation fault (core dumped)", which I think means that there is a denied memory access.

  int main( ) {
      Mat originalImage = imread("image.jpg", CV_LOAD_IMAGE_UNCHANGED); 
      if (originalImage.empty()){ 
          cout << "Error : Image cannot be loaded..!!" << endl;         
          return -1;
      } 
      int orgRows = originalImage.rows; 
      int orgCols = originalImage.cols;    
      int status; // output indicator

      cout << "Please select the settings" << endl; 
      cin >> status;   
      Mat displayedImage;  
      while (status != 0 ) {
          if(status == 1){
              // some code
          }
          else if (status == 2 ){   
              // some code  
          }else if (status == 3 ){
              int j;
              int k;            
              for (int i = 0; i < 1000; i++) {
                  j = rand()% orgCols;
                  k = rand() % orgRows;
                  Vec3b intensity = originalImage.at<Vec3b>(j, k);  
                  intensity[0] = 255;
                  intensity[1] = 255;
                  intensity[2] = 255;               
               }
               displayedImage = originalImage;
           }else if (status == 4){ 
               // some code
           }else if (status == 5 ){
               // some code
           }else{  
               // some code
           }
           namedWindow("MyWindow",CV_WINDOW_AUTOSIZE);
           imshow("MyWindow", displayedImage); 
           waitKey(1000);  
           destroyWindow("MyWindow");
           cout << "Continue ? ... Please select the settings" << endl; 
           cin >> status; 
      } 
  return 0;
}

Question:

What is causing the error and how could it be solved?


回答1:


You have 2 problems, both on this line:

Vec3b intensity = originalImage.at<Vec3b>(j, k);  
  1. Matrices are accessed as (row, col), not (x, y). So you need to use: Vec3b intensity = originalImage.at<Vec3b>(j, k);

  2. You are copying the pixel bgr value. Every change you do on intensity won't be reflected in originalImage. You can easily correct this using a reference to the data in originalImage: Vec3b& intensity = ....

As a result, you need to change the mentioned line to:

Vec3b& intensity = originalImage.at<Vec3b>(k, j);

Note: Using intensity[0] = 255; works ok. You don't need to use intensity.val[0] = 255;


Note that there are some improvements that you can do.

1) Since you work on Vec3b type, you make the assumption that your image is read as CV_8UC3, i.e. a 3 channel matrix, 8 bit depth per channel. So, if you load a 16bit image, or a single channel (grayscale) image, or an image with alpha channel (RGBA) your program will crash. You can enforce that you need a CV_8UC3 image while loading the image like:

Mat3b originalImage = imread("image.jpg", IMREAD_COLOR);

Now you can access the pixels value without the at<>, since the image type is fixed. So you can do:

Vec3b& intensity = originalImage(k, j); 

2) You can simply assign a new value to originalImage, like:

originalImage.at<Vec3b>(k,j) = Vec3b(255,255,255); 
//or
originalImage(k,j) = Vec3b(255,255,255); // If originalImage is a Mat3b



回答2:


Try this code. Now its working. You can't allocate a new pixel value by writing "intensity[0]" you have to use it with "intensity.val[0]" or "originalImage.at<cv::Vec3b>(k,j)[0] = 255;"

  #include <opencv\cv.h>
#include<highgui\highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main( ) {

  Mat originalImage = imread("p001.jpg", CV_LOAD_IMAGE_UNCHANGED); 

  if (originalImage.empty()){ 
    cout << "Error : Image cannot be loaded..!!" << endl;         
    return -1;
  } 
  int orgRows = originalImage.rows; 
  int orgCols = originalImage.cols;    
  int status; // output indicator
  cout << "Please select the settings" << endl; 
  cin >> status;   
  Mat displayedImage;  
    while (status != 0 ) {
        if(status == 1){
            // some code
        }
    else if (status == 2 ){   
            // some code  
        }else if (status == 3 ){
            int j=0;
            int k=0;          
      for (int i = 0; i < 1000; i++) {
                j = rand()% orgCols;
                k = rand() % orgRows;

               // Vec3b intensity = originalImage.at<Vec3b>(j, k);  

                originalImage.at<cv::Vec3b>(k,j)[0] = 255;
                originalImage.at<cv::Vec3b>(k,j)[1] = 255;
                originalImage.at<cv::Vec3b>(k,j)[2] = 255;
                /*intensity[0] = 255;
                intensity[1] = 255;
                intensity[2] = 255;     */            
        }
        displayedImage = originalImage;
        }else if (status == 4){ 
          // some code
        }else if (status == 5 ){
            // some code
        }else{  
        // some code
        }
        namedWindow("MyWindow",CV_WINDOW_AUTOSIZE);
        imshow("MyWindow", displayedImage); 
        waitKey(1000);  
        destroyWindow("MyWindow");
        cout << "Continue ? ... Please select the settings" << endl; 
        cin >> status; 
    }   
    return 0;
 }



回答3:


The problem is coming from you for loop:

Vec3b intensity = originalImage.at<Vec3b>(j, k);
-----^  
intensity[0] = 255;
intensity[1] = 255;
intensity[2] = 255; 

If you want to access (assign new value to) the RGB intensities at the random pixel: (j,k), you need to change it to reference of the original object:

Vec3b& intensity = originalImage.at<Vec3b>(j, k);

and use either of the methods for access:

intensity[0] = 255;
intensity[1] = 255;
intensity[2] = 255; 

or

originalImage.at<cv::Vec3b>(k,j)[0] = 255;
originalImage.at<cv::Vec3b>(k,j)[1] = 255;
originalImage.at<cv::Vec3b>(k,j)[2] = 255;

or:

Vec3b& intensity = originalImage.at<Vec3b>(j, k);  
intensity.val[0] = 255;
intensity.val[1] = 255;
intensity.val[2] = 255;

For further reading, check opencvexamples and opencv.org.



来源:https://stackoverflow.com/questions/32664332/accessing-random-image-pixels-using-a-for-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!