[python] OpenCV 공부노트 간단한 영상 조작

글쓴이 Engineer Myoa 날짜

[python]OpenCV 공부노트 Mat

 

개념이해를 위한 코드를 작성후

프로젝트채로 남겨두면 잘 안보게되어 주석을 달 만큼 달고

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개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다