使用for循环访问随机图像像素

时间:2015-09-19 04:49:23

标签: c++ opencv image-processing coredump

我正在尝试使用 OpenCV 学习图像处理。我写了一些代码来编辑图像。除了更改某些像素的颜色外,编辑工作正常。

我试图访问一些随机像素,并改变它们的颜色(即status == 3时)。当我运行程序时,我得到"[run] Segmentation fault (core dumped)",我认为这意味着存在被拒绝的内存访问。

  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;
}

问题:

导致错误的原因是什么?如何解决?

3 个答案:

答案 0 :(得分:2)

你有2个问题,都在这一行:

Vec3b intensity = originalImage.at<Vec3b>(j, k);  
  1. 矩阵的访问方式为(row,col),而不是(x,y)。所以你需要使用:Vec3b intensity = originalImage.at<Vec3b>(j, k);

  2. 您正在复制像素bgr值。您在intensity上所做的每项更改都不会反映在originalImage中。您可以使用对originalImage中的数据的引用轻松更正此问题:Vec3b& intensity = ...

  3. 因此,您需要将上述行更改为:

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

    注意:使用intensity[0] = 255;可以正常工作。您无需使用intensity.val[0] = 255;

    请注意,您可以进行一些改进。

    1)由于您处理Vec3b类型,因此您假设您的图像被读取为CV_8UC3,即3通道矩阵,每通道8位深度。因此,如果您加载16位图像,或单通道(灰度)图像,或带有Alpha通道(RGBA)的图像,您的程序将崩溃。您可以在加载图片时强制要求CV_8UC3图片,如:

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

    现在您可以在不使用at<>的情况下访问像素值,因为图像类型是固定的。所以你可以这样做:

    Vec3b& intensity = originalImage(k, j); 
    

    2)您可以简单地为originalImage分配一个新值,例如:

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

答案 1 :(得分:1)

试试这段代码。现在它的工作。您不能通过编写“intensity [0]”来分配新的像素值,您必须使用“intensity.val [0]”或“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;
 }

答案 2 :(得分:0)

问题来自你for循环:

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

如果要在随机像素(j,k)访问 RGB 强度(分配新值),则需要将其更改为原始对象的引用:

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

并使用以下任一方法进行访问:

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

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

或:

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

如需进一步阅读,请检查opencvexamplesopencv.org