彩色图像通道对齐示例
在多层彩色胶片尚未问世之前,拍摄彩色照片时所用的照相机..用一只普通照相机,三枚滤色镜(红、绿、蓝),要分别拍三次,得到红分底、绿分底、蓝分底.之后将三种颜色图形叠加还原成彩色照片。
但是由于三次拍摄的角度和位置不是完全一样的,叠加后不能完全对齐,于是结果可能是这样:
解决办法,以一个通道为基准,另外两个通道进行对齐,之后再合并:
OpenCV 课程作业:
读入图像,通道分离
cv::Mat ori_img = cv::imread("../result/reba_un_aligned.jpg");
cv::Mat channels[3];
cv::split(ori_img, channels);
将三个颜色的通道各自组合成三通道BGR 的图像
cv::Mat h10, h20;
cv::Mat blank_ch, bgr_b, bgr_g, bgr_r;
blank_ch =
cv::Mat::zeros(cv::Size(channels[0].cols, channels[0].rows), CV_8UC1);
cv::Mat channels_b[3]={channels[0], blank_ch, blank_ch};
cv::Mat channels_g[3]={blank_ch, channels[1], blank_ch};
cv::Mat channels_r[3]={blank_ch, blank_ch, channels[2]};
cv::merge(channels_b,3, bgr_b);
cv::merge(channels_g,3, bgr_g);
cv::merge(channels_r,3, bgr_r);
两辆通道之间进行对齐(透视变换)
FindHTotal(bgr_b, bgr_g,&h10);
cv::warpPerspective(channels[1], channels[1], h10,
cv::Size(blank_ch.cols, blank_ch.rows));
FindHTotal(bgr_b, bgr_r,&h20);
cv::warpPerspective(channels[2], channels[2], h20,
cv::Size(blank_ch.cols, blank_ch.rows));
查找透视变换矩阵
voidFindHTotal(const cv::Mat src, cv::Mat dst, cv::Mat* h_total){
printf("FindHTotal E\n");
cv::Mat gray1;
cv::Mat gray2;
cv::cvtColor(src, gray1, cv::COLOR_BGR2GRAY);
cv::cvtColor(dst, gray2, cv::COLOR_BGR2GRAY);
// cv::threshold(gray1, gray1, 123, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
// cv::threshold(gray2, gray2, 123, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
// cv::adaptiveThreshold(gray1, gray1, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C,
// cv::THRESH_BINARY, 25, 10);
// 1.
// key points
std::vector<cv::KeyPoint> key_points1;
std::vector<cv::KeyPoint> key_points2;
cv::Mat descriptors1, descriptors2;
// find key points
cv::Ptr<cv::ORB> orb = cv::ORB::create();
orb->detectAndCompute(gray1, cv::Mat(), key_points1, descriptors1);
orb->detectAndCompute(gray2, cv::Mat(), key_points2, descriptors2);
// 2.
// match key points
std::vector<cv::DMatch> matches;
cv::Ptr<cv::DescriptorMatcher> matcher =
cv::DescriptorMatcher::create("BruteForce-Hamming");
matcher->match(descriptors1, descriptors2, matches);
printf("matches.size() %lu\n", matches.size());
// sort key points
// Sort them in the order of their distance
std::sort(matches.begin(), matches.end());
// keep good matches
std::vector<cv::DMatch> good_matches;
int good_match_num = KEEP_MATCH_PERCENT * matches.size();
if(good_match_num <5&& matches.size()>=5){
good_match_num =5;
}
printf("good_match_num %d\n", good_match_num);
good_matches.assign(matches.begin(), matches.begin()+ good_match_num);
// Draw top matches
cv::Mat imMatches;
cv::drawMatches(src, key_points1, dst, key_points2, good_matches, imMatches);
cv::imwrite("../result/matches.jpg", imMatches);
// Extract location of good matches
std::vector<cv::Point2f> points1, points2;
for(size_t i =0; i < good_matches.size(); i++){
points1.push_back(key_points1[good_matches[i].queryIdx].pt);
points2.push_back(key_points2[good_matches[i].trainIdx].pt);
}
// cv::find h matrix
*h_total = cv::findHomography(points2, points1, cv::RANSAC);
printf("FindHTotal X\n");
// #if IM_SHOW
// cv::waitKey(0);
// cv::destroyAllWindows();
// #endif
}
合并对齐后的通道
cv::Mat new_channels[3]={channels[0], channels[1], channels[2]};
cv::Mat merged_img;
cv::merge(new_channels,3, merged_img);
[[2022-02-18-png 透明 alpha 通道]]