前提・実現したいこと
カメラからとってきた画像を任意のサイズで切り取り、処理するソフトを作成しています。
OpenCVを利用してカメラの画像を取得したので元の画像はMat形式なのですが、処理部分はunsigned charで処理をするのでMatからunsigned charへ変換する必要があります。
カメラからの画像はカラーなのですが、処理の都合グレースケールへ変換しています。2021/08/04追記
frame_buffer:カメラからの画像
frame_GRAY:グレースケールへ変換後の画像
C++
1 cv::cvtColor(frame_buffer,frame_GRAY,cv::COLOR_BGR2GRAY);
また、切り抜く幅が、4の倍数意外だと画像が乱れることが分かったので、一旦画像を大きく切り取ってunsigned charの変数へコピーした後、目的の大きさのunsigned charの変数へコピーをしています。
そこで下記のような関数を作成しました。
発生している問題・エラーメッセージ
エラーは起こっていないのですが、切り取る幅を4の倍数以外にすると画像が乱れてしまいます。
具体的には列ごとにずれが起こり、画像が斜めにゆがんだようになります。
また、画像の下部に想定している画像のデータ以外のものが入っているようで、黒い線が入ったようになります。
例 2021/08/04追記
処理する画像(グレースケール変換後)900×583pixel
幅300pixel 高さ300pixelで切り取り
幅301pixel 高さ300pixelで切り取り
該当のソースコード
C++
1void ConvMatToUchar(unsigned char *ucharImage, const cv::Mat* src, cv::Rect rect) 2{ 3 cv::Mat origin_img = *src; 4 cv::Rect tmp_rect = rect; 5 cv::Mat tmp_img; 6 7 //幅が4の倍数以外だと画像がずれるので、4の倍数になるように幅を延長。 8 int x_offset = 0; 9 int w_offset = 0; 10 int remain = rect.width % 4; 11 12 //画面右端での例外処理 13 if(remain != 0) 14 { 15 w_offset = 4 - remain; 16 if(rect.x + rect.width + w_offset > CAM_W) 17 { 18 x_offset = w_offset; 19 } 20 } 21 tmp_img = cv::Mat(origin_img,cv::Rect(rect.x + x_offset, rect.y, rect.width + w_offset, rect.height)).clone(); 22 23 //CAM_WとCAM_Hは元画像の幅と高さ 2021/08/04追記 24 unsigned char tmp_ucharImage[CAM_W * CAM_H]; 25 ::memcpy(tmp_ucharImage, tmp_img.data, static_cast<size_t>((rect.width + w_offset) * rect.height)); 26 for (int i = 0; i < rect.height; i++) 27 { 28 unsigned char *p = ucharImage + i * rect.width; 29 unsigned char *p_tmp = tmp_ucharImage + i * (rect.width + w_offset) + x_offset; 30 ::memcpy(p, p_tmp, static_cast<size_t>(rect.width)); 31 } 32 tmp_img.release(); 33}
表示部分2021/08/04追記
C++
1 int W = 301; 2 int H = 300; 3 cv::Rect cv_roi_rect = cv::Rect(0,0,W, H); 4 //関数の呼び出し 5 ConvMatToUChar(pbImage, &frame_GRAY, cv_roi_rect); 6 //Qtで表示 7 QImage tmp_img = QImage(pbImage, W, H, QImage::Format_Indexed8); 8 QPixmap tmp_pixmap = QPixmap::fromImage(tmp_img); 9 Scene.addPixmap(tmp_pixmap);
試したこと
unsigned char *p_tmp = tmp_ucharImage + i * (rect.width + w_offset) + x_offset;
上記の部分を下記のように変更すると、画像の斜めにゆがむことは解決できたように見えたのですが(Qtで表示)、下部の黒い線はなくなりませんでした。
unsigned char *p_tmp = tmp_ucharImage + i * rect.width + x_offset;
変更後画像 2021/08/04追記
幅301pixel 高さ300pixelで切り取り
また、処理後の画像を確認すると斜めにゆがんでおり、問題が解決したわけでもないようです。
このことから、どうも自分が考えているようなメモリの並びになっていないことは何となくわかったのですが、OpenCVに関する知識が不足しているため、どのようなメモリ構造で保持されているのかを理解することができませんでした。
補足情報(FW/ツールのバージョンなど)
開発環境
Windows10 64bit
Qt5.13.2
OpenCV 4.5.2
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。