검색결과 리스트
글
영상 정합(image patch similarity)
컴퓨터비전/영상처리
2015. 4. 4. 00:40
영상의 패치 정합
1. SSD(Sum of Squared Difference)
같은 위치에 있는 픽셀의 차를 구해서 제곱한 값을 다 더해 영역의 유사성 측정을 한다.
유사할 경우 0에 가깝다.
2. SAD(Sum Of Absolute Difference)
같은 위치에 있는 픽셀의 차를 절대값 하고 다 더해 영역의 유사성 측정을 한다.
SSD와 마찬가지로 유사할 경우 0에 가깝다.
3. NCC(Normalized Cross Correlation)
NCC는 SSD와 SAD가 갖는 밝기 차의 문제를 결하기 위해 사용하는 중 하나이다.
두 영역의 픽셀 평균값과 표준편차를 계산하여 평균 값기가 0, 표준편차는 1이 되도록 정규화한다.
m은 평균 밝기를 나타내며 σ는 표준편차이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | #include <cv.h> #include <highgui.h> #include <iostream> using namespace cv; using namespace std; int SSD(Mat &src1, Mat &src2, Point pt1, Point pt2, int patch_size) { // Range Check if ((pt1.x - patch_size) < 0 || (pt2.x - patch_size) < 0 || (pt1.x + patch_size) >= src1.rows || (pt2.x + patch_size) >= src2.rows || (pt1.y - patch_size) < 0 || (pt2.y - patch_size) < 0 || (pt1.y + patch_size) >= src1.cols || (pt2.y + patch_size) >= src2.cols) throw exception("SSD::Inavlid range"); // Image Channel Check if (src1.channels() != src2.channels()) throw exception("SSD::Image channel not same"); int nSum = 0; unsigned char *src1_ptr = (unsigned char*)src1.data; unsigned char *src2_ptr = (unsigned char*)src2.data; int src1_cn = src1.channels(); int src2_cn = src2.channels(); for (int r = -patch_size; r <= patch_size; r++) { for (int c = -patch_size; c <= patch_size; c++) { for (int l = 0; l <= src1_cn; l++) { nSum += ((src1_ptr[(pt1.x + r) * src1.cols * src1_cn + (pt1.y + c) * src1_cn + l]) - (src2_ptr[(pt2.x + r) * src2.cols * src2_cn + (pt2.y + c) * src2_cn + l])) * ((src1_ptr[(pt1.x + r) * src1.cols * src1_cn + (pt1.y + c) * src1_cn + l]) - (src2_ptr[(pt2.x + r) * src2.cols * src2_cn + (pt2.y + c) * src2_cn + l])); } } } return nSum; } int SAD(Mat &src1, Mat &src2, Point pt1, Point pt2, int patch_size) { // Range Check if ((pt1.x - patch_size) < 0 || (pt2.x - patch_size) < 0 || (pt1.x + patch_size) >= src1.rows || (pt2.x + patch_size) >= src2.rows || (pt1.y - patch_size) < 0 || (pt2.y - patch_size) < 0 || (pt1.y + patch_size) >= src1.cols || (pt2.y + patch_size) >= src2.cols) throw exception("SAD::Inavlid range"); // Image Channel Check if (src1.channels() != src2.channels()) throw exception("SAD::Image channel not same"); int nSum = 0; unsigned char *src1_ptr = (unsigned char*)src1.data; unsigned char *src2_ptr = (unsigned char*)src2.data; int src1_cn = src1.channels(); int src2_cn = src2.channels(); for (int r = -patch_size; r <= patch_size; r++) { for (int c = -patch_size; c <= patch_size; c++) { for (int l = 0; l < src1_cn; l++) { nSum += abs((src1_ptr[(pt1.x + r) * src1.cols * src1_cn + (pt1.y + c) * src1_cn + l]) - (src2_ptr[(pt2.x + r) * src2.cols * src2_cn + (pt2.y + c) * src2_cn + l])); } } } return nSum; } float NCC(Mat &src1, Mat &src2, Point pt1, Point pt2, int patch_size) { // Range Check if ((pt1.x - patch_size) < 0 || (pt2.x - patch_size) < 0 || (pt1.x + patch_size) >= src1.rows || (pt2.x + patch_size) >= src2.rows || (pt1.y - patch_size) < 0 || (pt2.y - patch_size) < 0 || (pt1.y + patch_size) >= src1.cols || (pt2.y + patch_size) >= src2.cols) throw exception("NCC::Inavlid range"); // Image Channel Check if (src1.channels() != src2.channels()) throw exception("NCC::Image channel not same"); // calcurate average, stendard deviation int nSum1 = 0, nSum2 = 0; int nSqr1 = 0, nSqr2 = 0; unsigned char *src1_ptr = (unsigned char*)src1.data; unsigned char *src2_ptr = (unsigned char*)src2.data; int src1_cn = src1.channels(); int src2_cn = src2.channels(); for (int r = -patch_size; r <= patch_size; r++) { for (int c = -patch_size; c <= patch_size; c++) { for (int l = 0; l < src1_cn; l++) { int t1 = src1_ptr[(pt1.x + r) * src1.cols * src1_cn + (pt1.y + c) * src1_cn + l]; int t2 = src2_ptr[(pt2.x + r) * src2.cols * src2_cn + (pt2.y + c) * src2_cn + l]; nSum1 += t1; nSum2 += t2; nSqr1 += t1 * t1; nSqr2 += t2 * t2; } } } int nPixels = (patch_size * 2 + 1) * (patch_size * 2 + 1); // pixel num float fMean1 = (float)nSum1 / (float)nPixels; float fMean2 = (float)nSum2 / (float)nPixels; float fVar1 = (float)nSqr1 / (float)nPixels - (float)fMean1 * (float)fMean1; float fVar2 = (float)nSqr2 / (float)nPixels - (float)fMean2 * (float)fMean2; // NCC float fSumNCC = 0.0f; for (int r = -patch_size; r <= patch_size; r++) { for (int c = -patch_size; c <= patch_size; c++) { for (int l = 0; l < src1_cn; l++) { fSumNCC += (float)((src1_ptr[(pt1.x + r) * src1.cols * src1_cn + (pt1.y + c) * src1_cn + l]) - fMean1) * ((src2_ptr[(pt2.x + r) * src2.cols * src2_cn + (pt2.y + c) * src2_cn + l]) - fMean2); } } } return fSumNCC / (fVar1 * fVar2); } int main() { Mat img, img2; img = imread("img/flower.jpg", 1); img2 = imread("img/flower.jpg", 1); int result_SSD = SSD(img, img2, Point(100, 100), Point(100, 100), 3); int result_SAD = SAD(img, img2, Point(100, 100), Point(100, 100), 3); float result_NCC = NCC(img, img2, Point(100, 100), Point(100, 100), 3); cout << "SSD = " << result_SSD << endl; cout << "SAD = " << result_SAD << endl; cout << "NCC = " << result_NCC << endl; namedWindow("image"); imshow("image", img); waitKey(); destroyAllWindows(); return 0; } | cs |
'컴퓨터비전/영상처리' 카테고리의 다른 글
옵티컬 플로우 Optical Flow -2 (0) | 2015.04.05 |
---|---|
옵티컬 플로우 Optical Flow -1 (0) | 2015.04.04 |
해리스 코너(Harris Corner) (2) | 2015.04.03 |
직선 검출 허프 변환 (0) | 2015.04.03 |
이미지 비율 유지 크기 조절 (0) | 2015.02.10 |