2017-11-09 2 views
3

값이 0 인 빈 행렬 hide_image을 만듭니다. 부적절합니다 - 672x896. 각 요소는 값으로 채워 져야합니다. 루프로 처리합니다. 그러나 (0, 299) 요소 코드에 예외를 던져 :cv :: cv :: Mat 객체를 루핑하는 동안 메모리 위치에 예외가 발생했습니다.

Unhandled exception at 0x00007FFD3C063C58 in stego.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000D2B033E5F0. occurred 

나는 기능을 디버깅과 예외가 루프에서 J 값의 의존하는 것을 발견했다. j를299로 설정하면 프로그램이 문제없이 작동하지만 모든 행렬이 필요합니다. 명령 줄에 다음 메시지가 표시됩니다.

OpenCV Error: Assertion failed ((unsigned)(i1 * DataType<_Tp>::channels) < 
(unsigned)(size.p[1] * channels())) in cv::Mat::at, file c:\opencv- 
3.3.1\opencv\build\include\opencv2\core\mat.inl.hpp, line 1095 

잘못된 행렬 초기화로 인해 문제가 발생할 수 있지만 그 이유는 무엇입니까? 행 수가 맞고 j를298로 설정하면 루프는 i = 671에서 끝납니다. 그러나 기둥이 적어서 숫자 299가 아무 것도에 의존하지 않는 것 같습니다.

cv::Mat hide_image; 
int hide_image_cols = 0, hide_image_rows = 0; 
int i_current = 0, j_current = 15; 
int curr_bit = 0; 

get_img_dim(image, hide_image_cols, hide_image_rows); 

hide_image = cv::Mat(hide_image_rows, hide_image_cols, CV_8U); 
hide_image = cv::Mat::zeros(hide_image_rows, hide_image_cols, CV_8U); 
std::cout << (hide_image.at<cv::Vec3b>(671, 299)) << std::endl; // exception 

for (int i = 0; i < hide_image.rows; i++) 
for (int j = 0; j < hide_image.cols; j++) { 
//exception when j>298 
std::cout << (hide_image.at<cv::Vec3b>(i, j)) << std::endl; 
} 

왜이 예외가 발생합니까? 초기화 동안

답변

2

할 경우 BTW

이 줄

hide_image = cv::Mat(hide_image_rows, hide_image_cols, CV_8U); 

문제가 행렬 데이터 타입 및 방법에서는 요소에 액세스 함께 불필요하다.

Mat을 초기화 할 때 채널 수가 지정되지 않은 경우 OpenCV는 기본적으로 단일 채널을 사용합니다. 즉, 데이터 유형 CV_8U을 지정한 경우 hide_imageCV_8UC1이됩니다.

루프에서는 행렬 요소가 CV_8UC3 인 것으로 가정하는 데이터 유형 cv::Vec3b을 사용하여 행렬 요소에 액세스합니다. 따라서, 원하는 경우 1 바이트 대신 3 바이트 씩 점프하여 행렬을 반복합니다.

이 시나리오에서 숫자 299은 실제로 코드 충돌에 중요한 역할을합니다. 행렬의 열 수는 입니다.코드는 298 * 3 = 894이고 인덱스 894는 hide_image의 유효한 메모리 주소에 해당하기 때문에 인덱스 298까지 작동해야합니다. j이 299 일 때 루프는 299 * 3 = 897에 액세스하려고 시도하며 이로 인해 외부 메모리에 액세스 할 수 없습니다.

따라서이 시나리오의 솔루션은 초기화 및 요소 액세스의 데이터 유형이 동일한 지 확인하는 것입니다. 따라서 다음 중 하나가 효과가 있습니다.

3 채널로 입력 행렬을 만듭니다.

hide_image = cv::Mat::zeros(hide_image_rows, hide_image_cols, CV_8UC3); 

OR

액세스 등이 하나의 채널 매트릭스에 알맞은 데이터 형식으로 요소 :

std::cout << (hide_image.at<unsigned char>(i, j)) << std::endl; 
3
하면 초기화 매트릭스를 통해 루프하는 다른 유형의 사용

...

당신은 8 비트 화소 표현 (한 개의 채널) 인 CV_8U를 사용한다.

hide_image = cv::Mat(hide_image_rows, hide_image_cols, CV_8U); 
hide_image = cv::Mat::zeros(hide_image_rows, hide_image_cols, CV_8U); 

는 그러면 (CV_8UC3 상당) 픽셀 당 24 비트이다 Vec3b를 사용한다. 따라서 데이터를 3 배 빨리 압축하면 데이터가 부족하여 세그먼트 화 오류가 발생합니다. 대신 CV_8UCV_8UC3

초기화 또는 uchar 대신 Vec3b를 사용

for (int i = 0; i < hide_image.rows; i++) 
    for (int j = 0; j < hide_image.cols; j++) { 
    //exception when j>298 
    std::cout << (hide_image.at<cv::Vec3b>(i, j)) << std::endl; 
    } 

당신은 무엇을 할 수 있습니다. 만약 다음 라인을

hide_image = cv::Mat::zeros(hide_image_rows, hide_image_cols, CV_8U); 
관련 문제