指定矩形の画像をもう一つの指定矩形に対して射影変換して埋め込むというプログラムを書いています。
一応完成はしたのですが、imageA.jpgという画像以外で試すと落ちてしまいます。
どうしたら他画像も読み込んでくれるでしょうか?
以下コードです。
c++
1#include <opencv2/opencv.hpp> 2 3using namespace std; 4 5cv::Mat imageA; //入力画像1 6cv::Mat imageP; //枠線記憶用画像 7cv::Mat imageL; //マウス入力用表示画像 8cv::Mat mask; //マスク画像 9cv::Mat pers; //変換後のimage 10cv::Mat results; 11 12cv::Point startp; //四角形の始点 13cv::Point secondp; //四角形の第2点 14cv::Point thirdp; //四角形の第3点 15cv::Point endp; //四角形の終点 16 17cv::Point startp2; //四角形の始点 18cv::Point secondp2; //四角形の第2点 19cv::Point thirdp2; //四角形の第3点 20cv::Point endp2; //四角形の終点 21 22int p_count = 0; 23cv::Scalar line_color = cv::Scalar(0, 250, 0); // 線の色 (default 緑) 24cv::Scalar line_color2 = cv::Scalar(250, 0, 0); // 線の色 (default 赤) 25 26void onFourMouseClicks(int event, int x, int y, int flag, void *param) 27{ 28 using namespace cv; 29 Mat *mat = static_cast<Mat *>(param); // param は imageLine 30 imageL = mat->clone(); //マウス移動中の表示用画像 31 32 switch (event) 33 { 34 case cv::MouseEventTypes::EVENT_LBUTTONDOWN: //左ボタンが押されたら 35 if (p_count == 0 || p_count == 8) 36 { 37 std::cout << "始点:(" << x << " , " << y << ")" << endl; 38 39 imageP = results.clone();//枠線表示用画像 40 imageL = results.clone(); 41 startp.x = x; 42 startp.y = y; 43 p_count = 1; 44 break; 45 } 46 else if (p_count == 1) 47 { 48 std::cout << "第2点:(" << x << " , " << y << ")" << endl; 49 secondp.x = x; 50 secondp.y = y; 51 line(imageP, startp, secondp, line_color, 2); //1→2の直線描画 52 p_count = 2; 53 break; 54 } 55 else if (p_count == 2) 56 { 57 std::cout << "第3点:(" << x << " , " << y << ")" << endl; 58 thirdp.x = x; 59 thirdp.y = y; 60 line(imageP, secondp, thirdp, line_color, 2); //2→3直線描画 61 p_count = 3; 62 63 break; 64 } 65 else if (p_count == 3) 66 { 67 std::cout << "終点:(" << x << " , " << y << ")" << endl; 68 endp.x = x; 69 endp.y = y; 70 p_count = 4; 71 line(imageP, thirdp, endp, line_color, 2); //3→4直線描画 72 line(imageP, endp, startp, line_color, 2); //4→1直線描画 73 break; 74 } 75 else if(p_count == 4) 76 { 77 std::cout << "始点:(" << x << " , " << y << ")" << endl; 78 startp2.x = x; 79 startp2.y = y; 80 p_count = 5; 81 break; 82 } 83 else if(p_count == 5) 84 { 85 std::cout << "第2点:(" << x << " , " << y << ")" << endl; 86 secondp2.x = x; 87 secondp2.y = y; 88 line(imageP, startp2, secondp2, line_color2, 2); //1→2の直線描画 89 p_count = 6; 90 break; 91 } 92 else if(p_count == 6) 93 { 94 std::cout << "第3点:(" << x << " , " << y << ")" << endl; 95 thirdp2.x = x; 96 thirdp2.y = y; 97 line(imageP, secondp2, thirdp2, line_color2, 2); //2→3直線描画 98 p_count = 7; 99 break; 100 } 101 else if(p_count == 7) 102 { 103 std::cout << "終点:(" << x << " , " << y << ")" << endl; 104 endp2.x = x; 105 endp2.y = y; 106 p_count = 8; 107 line(imageP, thirdp2, endp2, line_color2, 2); //3→4直線描画 108 line(imageP, endp2, startp2, line_color2, 2); //4→1直線描画 109 110 pers = Mat::zeros(imageA.rows, imageA.cols, CV_8UC3); 111 // 左上、右上、右下、左下 が標準 112 const Point2f src_pt[] = { 113 Point2f(startp.x, startp.y), 114 Point2f(secondp.x, secondp.y), 115 Point2f(thirdp.x, thirdp.y), 116 Point2f(endp.x, endp.y)}; 117 const Point2f dst_pt[] = { 118 Point2f(startp2.x, startp2.y), 119 Point2f(secondp2.x, secondp2.y), 120 Point2f(thirdp2.x, thirdp2.y), 121 Point2f(endp2.x, endp2.y)}; 122 cv::Mat pers_mat = getPerspectiveTransform(src_pt, dst_pt); 123 // 射影変換行列pers_matにより,warpPerspectiveを用いて画像を変換 124 warpPerspective(imageA, pers, pers_mat, pers.size()); 125 imshow("mouse input window", imageP); 126 break; 127 } 128 case cv::MouseEventTypes::EVENT_MOUSEMOVE: 129 if (p_count == 1) 130 line(imageL, startp, Point(x, y), line_color, 2); //1→mouse直線描画 131 else if (p_count == 2) 132 line(imageL, secondp, Point(x, y), line_color, 2); //2→mouse直線描画 133 else if (p_count == 3) 134 line(imageL, thirdp, Point(x, y), line_color, 2); //3→mouse直線描画 135 else if (p_count == 5) 136 line(imageL, startp2, Point(x, y), line_color2, 2); //3→mouse直線描画 137 else if (p_count == 6) 138 line(imageL, secondp2, Point(x, y), line_color2, 2); //3→mouse直線描画 139 else if (p_count == 7) 140 line(imageL, thirdp2, Point(x, y), line_color2, 2); //3→mouse直線描画 141 //imshow("mouse input window", imageL); 142 break; 143 } 144} 145 146// マウスクリックした4点を4隅とするマスク画像(背景:黒(0),マスク:白(255))を生成する 147void makeMask(char **args) 148{ 149 imageA = cv::imread(args[0]); 150 if (imageA.empty()) 151 { 152 cout << "画像読み込み失敗" << endl; 153 return; 154 } 155 156 //クリック位置記憶用画像 157 imageP = imageA.clone(); 158 //マウス入力用画像 159 imageL = imageA.clone(); 160 //結果画像 161 results = imageA.clone(); 162 //マスク画像の初期化 163 mask = cv::Mat::zeros(imageA.size(), CV_8UC1); 164 165 //ウィンドウ作成 166 cv::namedWindow("mouse input window"); 167 168 cv::Mat images[] = {imageA, imageP, imageL}; 169 cv::setMouseCallback("mouse input window", onFourMouseClicks, (void *)&images); 170 171 //「q」が押されたら終了 172 while (true) 173 { 174 //画像の表示 175 cv::imshow("mouse input window", imageP); 176 switch (cv::waitKey(33)) 177 { 178 case 'c': 179 if (p_count == 8) 180 { // 4点クリックが終わっていたならば 181 mask = cv::Mat::zeros(results.size(), CV_8UC1); //マスク画像の0初期化 182 // vector<vector<cv::Point>> contour; //輪郭情報はPointの配列(ベクタ)の配列(ベクタ) 183 cv::drawContours(mask, vector<vector<cv::Point>>{{startp2, secondp2, thirdp2, endp2}}, 0, cv::Scalar::all(255), cv::FILLED); 184 cv::Mat srcA, srcB; 185 cv::resize(results, srcA, cv::Size(640, 480)); // BGRの3チャンネル画像 186 srcB = pers; // BGRの3チャンネル画像 187 188 cv::Mat result(cv::Size(srcA.cols, srcA.rows), CV_8UC3); 189 190 for (int y = 0; y < srcA.rows; y++) 191 { 192 uchar *p = srcB.ptr(y); 193 uchar *q = srcA.ptr(y); 194 uchar *m = mask.ptr(y); 195 uchar *r = result.ptr(y); 196 for (int x = 0; x < srcA.cols; x++) 197 { //マスクは1チャネル,他は3チャネル 198 r[x * 3] = p[x * 3] * m[x] / 255 + q[x * 3] * (255 - m[x]) / 255; 199 r[x * 3 + 1] = p[x * 3 + 1] * m[x] / 255 + q[x * 3 + 1] * (255 - m[x]) / 255; 200 r[x * 3 + 2] = p[x * 3 + 2] * m[x] / 255 + q[x * 3 + 2] * (255 - m[x]) / 255; 201 } 202 } 203 cv::imshow("Blending Result", result); 204 results = result; 205 p_count = 0; // 4点クリックは最初から 206 } 207 break; 208 case 'a': 209 imageP = results.clone(); 210 imageL = results.clone(); 211 cv::destroyWindow("Blending Result"); 212 p_count = 0; // 4点クリックは最初から 213 break; 214 case 's': // その時点の mask を保存 215 cv::imwrite("resultMasked.png", results); 216 cout << "saved to resultMasked.png" << endl; 217 break; 218 case 'R': // 最初に戻る 219 imageP = imageA.clone(); 220 imageL = imageA.clone(); 221 results = imageA.clone(); 222 p_count = 0; // 4点クリックは最初から 223 cv::destroyWindow("Blending Result"); 224 cout << "画像のリセット" << endl; 225 break; 226 case 'r': // 最初に戻る 227 imageP = results.clone(); 228 imageL = results.clone(); 229 p_count = 0; // 4点クリックは最初から 230 cv::destroyWindow("Blending Result"); 231 cout << "クリックのリセット" << endl; 232 break; 233 case 'q': 234 return; 235 } 236 } 237} 238 239int main(int argc, char *argv[]) 240{ 241 // makeMask関数に渡す配列の宣言 242 char *args[1] = {"imageA.jpg"}; 243 if (argc >= 2) 244 args[0] = argv[1]; //引数での入力画像指定 245 246 makeMask(args); 247 return 0; 248}
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。