최근 프로그래머스 알고리즘 공부를 하던 중 예상치 못한 논리오류를 겪으며 원인을 찾아 헤맸는데

알고보니 메소드 호출 시 파라미터의 데이터 타입에 따라

Call by Reference가 발생하는 경우를 생각하지 못했기 때문이었다.

따라서 이런저런 테스트를 통해 배운 내용을 정리하고자 한다.

 

 

 

 


 

 

 

 

 

Java의 데이터 타입에는 기본형, 참조형으로 크게 2가지가 있다.

 

 

기본형 타입 (Primitive Type)

Boolean   Byte   Short   Int   Long   float   Double   Char

 

 

 

 

 

이렇게 총 8가지의 데이터 타입이 기본형이다.

 

이 데이터 타입은 스택(Stack) 메모리에 실제 데이터를 저장하며

메소드의 파라미터로 전달할 경우 Call by Value 형식으로 전달된다.

따라서 메소드에서 데이터를 변경하더라도 원본 데이터는 영향을 받지 않는다.

 

 

 

 



 

 

위를 실행시킨 결과

 

 

 


 

 

 

 

 

 

참조형 타입(Reference Type)

배열(Array), 열거(Enumeration), 클래스(Class), 인터페이스(Interface)

 

 

 

 

 

해당 데이터 타입은 Heap 영역에 선언된 인스턴스( ex) Test t; )가 저장되고

해당 인스턴스의 메소드 등에 접근하기 위해 저장된 스택 메모리의 참조값이 할당된다.

 

 

 

참고로 참조형 타입의 경우 == 연산자를 사용하면 참조값을 비교하게 되기 때문에
Array의 equal()과 같은 비교 메소드를 호출해주어야 한다.

 

 

 

따라서 메소드의 파라미터로 참조형 타입을 전달하면 참조값을 전달하기 때문에 ( Call by reference )

메소드 내에서 변경 시 원본 값이 변경된다.

 

배열, ArrayList, LinkedList 등을 메소드로 전달해 사용할 때는 새 인스턴스에 복사하여 사용하는 것이 좋다.

 

 

 

 

 


 

 

 


 

위를 실행시킨 결과

 

 

 


 

혹시 내용에 오류가 있다면 지적 부탁드립니다:)

반응형

'Java' 카테고리의 다른 글

[JAVA] Java 구성요소  (0) 2021.03.06

최근 손가락 검출 및 이벤트 맵핑 프로젝트를 진행했었는데 그 일부분을 정리해 하나씩 올려보고자 한다.

 

아래 코드는 피부색을 검출하기 전 단계로 피부색 검출 시 얼굴과 손이 동시에 검출되는 것을 막기 위해 ROI(Region Of Interest | 관심 영역)로 설정한 부분을 따로 크롭하여 분리한다.

이 방법은 쉽고 단순한 방법이며, Feature 기반 API를 활용하지 않고 사용할 수 있는 방법이다.

 

전체 코드는 맨 아래에 기술해두었다.


Mat frame, crop;	//frame : 웹캠 프레임, crop : 웹캠 프레임에서 크롭된 이미지
VideoCapture cap;	//웹캠

int deviceID = 0;	//디폴트 카메라
int apiID = CAP_ANY;	//디폴트 API

cap.open(deviceID, apiID);	//웹캠 열기

//웹캠 오류 확인
if (!cap.isOpened()) {
	cerr << "ERROR! Unable to open the camera\n";
	return -1;
}

우선 VideoCapture 객체를 선언한다.

open함수의 첫번째 인자로 0을 넣게 되면 디폴트로 설정된 카메라를 사용하게 된다.

 

 

VideoCapture는 웹캠뿐 아니라 비디오 파일도 불러올 수 있다.

 

VideoCapture cap("비디오파일.mp4") 으로 입력하면 exe파일 실행 시 같은 폴더 내에 보관된 지정된 이름의 비디오 파일을 불러오게 된다.(mp4는 예시이다) 

main함수 인자로 argc, argv를 입력하고 비디오파일 이름 대신 argv[1]을 넣게 되면 cmd창에 두 번째 인자로 입력한 비디오 파일을 불러온다. cmd창의 두 번째 인자를 경로와 함께 입력하면 꼭 exe파일과 같은 폴더 내에 있지 않아도 불러올 수 있다.

 

if문은 웹캠이 열리지 않았을 경우 예외처리를 해주는 부분인데, 예외처리를 해주는 편이 좋다.

 

 


Rect rect(350, 100, 200, 200);	//크롭 영역

//웹캠 출력
for (;;) {
	cap.read(frame);

	if (frame.empty()) {
		cerr << "ERROR! blank frame grabbed\n";
		break;
	}

	//좌우반전
	flip(frame, frame, 1);

	//영상 크롭
	crop = frame(rect);
    
	//크롭되는 영역 표시
	rectangle(frame, Point(350, 100), Point(550, 300), CV_RGB(255, 0, 0));

	imshow("Live", frame);
	imshow("crop", crop);

	//아무 키나 누르면 종료
	if (waitKey(5) >= 0) {
		break;
	}
}

웹캠을 포함해서 모든 비디오는 낱개의 이미지가 초당 몇장씩 연결해 보여주는 것으로 이해하면 된다.

for(;;) 또는 while(1)문으로 무한 루프를 돌리는 이유가 이 때문이다.

 

화면은 웹캠을 통해 받은 이미지를 Mat 변수에 따로 저장하여 imshow로 보여주면 된다.

 

역시 프레임을 받지 못했을 경우를 예외처리 해준다.

 

웹캠을 그냥 켜게 되면 좌우가 반대로 보이는데, 이 부분이 불편하니 우리가 일반적으로 거울을 보는 것처럼 보기 위해 좌우반전을 해준다.

 

Rect객체는 인자로

(왼쪽 위 x포인트, 왼쪽 위 y포인트, 사각형 가로 크기, 사각형 세로 크기)

이렇게 넣어주면 된다.

 

rectangle 함수는 ROI 영역을 명시적으로 보여주기 위해 그려준다. 이 영역 안에 손을 올리면 된다.

 

아무 키나 누르면 무한루프를 빠져나오도록 구현했다.

 

 

 

전체 코드


#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main() {
	Mat frame, crop;	//frame : 웹캠 프레임, crop : 웹캠 프레임에서 크롭된 프레임
	VideoCapture cap;	//웹캠	
	Rect rect(350, 100, 200, 200);	//크롭 영역

	
	int deviceID = 0;		//디폴트 카메라
	int apiID = CAP_ANY;	//디폴트 API

	//웹캠 열기
	cap.open(deviceID, apiID);

	namedWindow("Live");
	namedWindow("crop");

	//웹캠 오류 확인
	if (!cap.isOpened()) {
		cerr << "ERROR! Unable to open the camera\n";
		return -1;
	}

	//웹캠 출력
	for (;;) {
		cap.read(frame);

		if (frame.empty()) {
			cerr << "ERROR! blank frame grabbed\n";
			break;
		}

		//좌우반전
		flip(frame, frame, 1);


		//영상 크롭
		crop = frame(rect);

		//크롭되는 영역 표시
		rectangle(frame, Point(350, 100), Point(550, 300), CV_RGB(255, 0, 0));

		imshow("Live", frame);
		imshow("crop", crop);

		//아무 키나 누르면 종료
		if (waitKey(5) >= 0) {
			break;
		}
	}

	return 0;

}

 

 

 

 

혹시나 틀린 부분이 있다면 지적 환영합니다:)

응원 댓글은 작성자에게 큰 힘이 됩니다!

반응형

+ Recent posts