[python] OpenCV 공부노트 간단한 영상 조작
개념이해를 위한 코드를 작성후
프로젝트채로 남겨두면 잘 안보게되어 주석을 달 만큼 달고
techlog에 보관하는 편을 선택했다.
직선 클리핑
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat someImage(512, 512, CV_8UC3, Scalar(255, 255, 255)); if (someImage.empty()) { return -1; } Rect imgRect(100, 100, 300, 300); rectangle(someImage, imgRect.tl(), imgRect.br(), Scalar(255, 0, 0), 2); Point pt1(10, 50), pt2(450, 600); //line(someImage, pt1, pt2, Scalar(0, 255, 0), 2); clipLine(imgRect, pt1, pt2); // clipLine은 주어진 Mat클래스에 pt1 -> pt2 사이에 직선을 긋고 가로지르는 영역이 존재하면 pt1, pt2에 해당 영역을 지정한다. // 그래서 imgRect라는 사각형객체와 pt1-pt2 직선이 서로 교차하는 부분의 좌표지점(2개)을 pt1, pt2에 저장 // 어떤 도형이던 직선이 가로질럿을때는 2개의 접점밖에 발생하지 않음 cout << "pt1 = " << pt1 << endl; cout << "pt2 = " << pt2 << endl; circle(someImage, pt1, 5, Scalar(0, 0, 255), 2); circle(someImage, pt2, 5, Scalar(0, 0, 255), 2); line(someImage, pt1, pt2, Scalar(255, 0, 0), 2); imshow("test", someImage); waitKey(0); return 0; }
LineIterator 사용하기
기존의 MatConstIterator 클래스 객체를 사용했다면 이번엔 특정 라인을 지정하여
해당 라인이 지나가는 각 화소들에 대해 Iterating 할 수 있는 클래스이다.
현재 lena를 흑백으로 불러오고 라인이터레이팅을 한다음
그 값들을 히스토그램으로 표현하려고하는데,
기존의 예제에서는 Mat클래스를 새로 생성해서 빈화면 (Scalar(255,255,255))에 히스토그램 그래프만 그렸다.
조금 발전시켜서 이미지를 통째로 복사하고 거기에 히스토그램을 그려보도록했다.
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat lena = imread("lena.jpg", IMREAD_GRAYSCALE); if (lena.empty()) { return -1; } Point pt1(10, 10), pt2(400, 400); LineIterator iter(lena, pt1, pt2, 8); vector<uchar> buffer(iter.count); cout << iter.count << endl; // iter.count의 갯수가 400-10이 될것인가? -> 정답. 하지만 정확하게는 0~400 이므로 401개 - 10개 = 391 for (int i = 0; i < iter.count; i++, ++iter) { buffer[i] = **iter; // buffer[i] = *(const Vec3b)*it; // 8비트 3채널인경우 // buffer[i] = lena.at<Vec3b>(it.pos()); // 8비트 3채널인 경우 } //cout << (Mat)buffer << endl; line(lena, pt1, pt2, Scalar(150,150,150), 1); Mat someImage(lena.rows, lena.cols, CV_8UC3, Scalar(255, 255, 255)); MatConstIterator_<uchar> matIter = lena.begin<uchar>(); for (int i = 0; i < lena.cols; i++) { for (int j = 0; j < lena.rows; j++) { //cout << *matIter << endl; someImage.at<Vec3b>( Point(j, i) )[1] = *matIter; someImage.at<Vec3b>(Point(j, i))[0] = *matIter; // [0]에 접근. Vec3b는 3채널의 값이고 uchar는 1채널의 값이기때문 someImage.at<Vec3b>(Point(j, i))[2] = *matIter; // uchar를 Vec3b로 어떻게 변환할까했더니 전부다 같은 값을 주면 되는거였음.. matIter++; } } pt1 = Point(0, lena.cols - buffer[0]); // line때문에 첫 포인트 (buffer[0])를 고정 for (int i = 1; i < buffer.size(); i++, ++iter) { pt2 = Point(i, someImage.cols - buffer[i]); line(someImage, pt1, pt2, Scalar(50,240,50), 2); pt1 = pt2; } imshow("graph", someImage); waitKey(0); return 0; }
어떻게 Vec3b에 uchar값을 대입할까.. 고민하던찰나에
너무 단순한 것을 잊어먹고있었다.
Vec3b나 uchar Matrix 모두 “2차원” 행렬이다.
다시말하면
[ (0), (255), (128),
(100), (64), (32) ]와 (uchar Matrix)
[ (0,0,0), (255,255,128), (128,128,128),
(1,10,100), (16,32,64), (32,64,128)] 의 차이(Vec3b Matrix)일 뿐이다.
다시말하면 3개의 Vector요소를 갖고있으므로 3요소 모두 같은 GrayScale 8bits 값을 채워넣으면 되는 것이다.
5개의 댓글