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