我正在尝试使用 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;
}
导致错误的原因是什么?如何解决?
答案 0 :(得分:2)
你有2个问题,都在这一行:
Vec3b intensity = originalImage.at<Vec3b>(j, k);
矩阵的访问方式为(row,col),而不是(x,y)。所以你需要使用:Vec3b intensity = originalImage.at<Vec3b>(j, k);
您正在复制像素bgr值。您在intensity
上所做的每项更改都不会反映在originalImage
中。您可以使用对originalImage
中的数据的引用轻松更正此问题:Vec3b& intensity = ...
。
因此,您需要将上述行更改为:
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;
如需进一步阅读,请检查opencvexamples和opencv.org。