У меня есть код C++, написанный с использованием OpenCv, который хорошо работает на моих изображениях. Но, поскольку код занимает слишком много времени, я решил изменить каждый размер изображения и сохранить его в папке. Часть кода, написанного в Matlab, где я переформатирую изображения, выглядит следующим образом:
%read image
image=imread(char(image_name));
%The image will become 4 times smaller
img_resized=imresize(image,0.25);
%save the image with the same name, but now it is smaller
C = regexp(char(image_name),'/','split');
imwrite(img_resized, [name_folder '/' char(C(end))]);
Что действительно странно, когда я запускаю код C++ на этих измененных изображениях, я получаю ошибку ошибки сегментации. Когда я запускаю исходные изображения, код работает хорошо.
Ошибка при возврате кода при изменении размеров изображений. Здесь beach_wood_copy_r8.png - это измененное изображение
./zernike beach_wood_copy_r8.png beach_wood_gt_r8.png resu.png
Reading Images
Calculating Zernike
Segmentation fault (core dumped)
И есть часть исходного кода C++, где происходит ошибка:
int main(int argc, char** argv){
int r, c, nDegree, nBlockSize;
printf("Reading Images\n");
BYTE** pSrc = getImage(argv[1], r, c);
BYTE** pGround = getImage(argv[2], r, c);
set<pair<int, int>, LessFunctionClass> matchedIndex;
time_t start_time, end_time, prog_time;
start_time = time(NULL);
nDegree = 6;
nBlockSize = 24;
printf("Calculating Zernike\n");
//error happens here
calculateZernike(pSrc, r, c, nDegree, nBlockSize);
printf("Zernike calculated\n");
EDIT: функция getImage находится в следующих строках:
BYTE** getImage(char* fName, int& r, int& c){
IplImage* img = cvLoadImage(fName, CV_LOAD_IMAGE_GRAYSCALE);
int i, j;
BYTE **pSrc;
c = img->width;
r = img->height;
pSrc = new BYTE*[r];
for(i=0; i<r; i++){
pSrc[i] = new BYTE[c];
}
for(i=0; i<r; i++){
for(j=0; j<c; j++){
pSrc[i][j] = img->imageData[i*c + j];
}
}
cvReleaseImage( &img);
return pSrc;
}
EDIT 2 Вот где исходный код вычисляет zernike моменты:
void calculateZernike(BYTE **p_block, int r, int c, int degree, int blockSize)
{
int i, j, k, l, m, n, numDegree;
double pi;
pi = acos(-1.0);
COMPLEX ***p_Vnm = getZernikePolynomial(blockSize, degree);
numDegree = 0;
for(i=0; i<degree; i++){
numDegree += (i/2+1);
}
for(i=0; i<c-blockSize+1; i=i+1){
for(j=0; j<r-blockSize+1; j=j+1){
BlockInfo zResult;
zResult.m_x = i;
zResult.m_y = j;
int zDegree = 0;
for(n=0; n<degree; n++){
for(m=0; m<=n; m++){
if( (n-m)%2 == 0 ){
COMPLEX sumValue;
sumValue.r = 0;
sumValue.j = 0;
for(k=0; k<blockSize; k++){
for(l=0; l<blockSize; l++){
sumValue.r += p_Vnm[zDegree][k][l].r * p_block[j+k][i+l];
sumValue.j += p_Vnm[zDegree][k][l].j * p_block[j+k][i+l];
}
}
sumValue.j *= (n+1)/pi;
sumValue.r *= (n+1)/pi;
double tempMag, tempPhase;
tempMag = sqrt(sumValue.j*sumValue.j + sumValue.r*sumValue.r);
tempPhase = atan2(sumValue.r, sumValue.j);
sumValue.r = tempMag;
sumValue.j = tempPhase;
zResult.ZMM.push_back(sumValue);
zDegree++;
}
}
}
blockZMMs.push_back(zResult);
}
}
for (i=0; i<numDegree; i++){
for(j=0; j<blockSize; j++){
delete [] p_Vnm[i][j];
}
delete [] p_Vnm[i];
}
delete p_Vnm;
return ;
}
Я думаю, что C++ не может открыть измененные изображения. Что я могу сделать, чтобы исправить это?
Как мы уже говорили в комментариях, в коде вычисления моментов Церника, два внутренние большинством for
петель пытаются получить доступ к пикселям, которые находятся вне границ в изображении. Чтобы этого избежать, попробуйте написать следующую инструкцию if
перед выполнением любых вычислений:
for (k = 0; k < blockSize; k++) {
for (l = 0; l < blockSize; l++) {
// Change here
if (j+k < 0 || j+k >= r || i+l < 0 || i+l >= c)
continue;
sumValue.r += p_Vnm[zDegree][k][l].r * p_block[j+k][i+l];
sumValue.j += p_Vnm[zDegree][k][l].j * p_block[j+k][i+l];
}
}
Оператор if
в цикле for
должен предотвращать доступ к пикселам, которые находятся за пределами размеров изображения. Эта защита не была здесь раньше в вашем коде.
r
иc
после изменения размеров изображений?r
иc
жестко запрограммированы в вашей C ++ программе? Я не вижу, чтобыr
иc
читались или устанавливались где-либо, поэтому я предполагаю, что это делается за пределамиmain
.