상황

일하고 있는 곳 에서 반도체 불량 검출 GUI제작 프로젝트를 진행하던 중 C#에서 검사에 사용하기로 한 파라미터들의 정보를 저장 해둔 클래스를 구조체로 바꾸어서 작업을 해야 하기로 이야기가 나오게 되었고  

클래스 -> 구조체로 바꾸는 작업을 다른 팀원이 하고 프로그램을 돌려본 결과 기존에 마우스 조작 이벤트로 잘 그려지던 (Roi)관심 영역 바운딩 박스가 그려지지 않는다는 이슈사항이 발생하였다.

 

<기능이 제대로 수행되는 상황>

<클래스 -> 구조체 이슈 이후>

처음에 마우스 클릭으로 좌표가 잡히긴 하지만 드레그 이벤트가 아예 동작하지 않았다.

 

또 내가 코드를 어디 잘 못 짰겠구나 싶어 디버깅 하며 원인을 찾던 중 로직에서 문제가 될 것 이라 추정되는 부분을 찾을 수 있었다.

<문제가 일어난 걸로 추측되는 코드>

        private void UpdateRoi(MouseEventArgs e, List<Roi> roiList, List<Roi> calibratedRoiList)
        {
            if (roiList.Count == 0) return;

            int mouseX = Math.Min(e.X, PictureBox.Width);
            int mouseY = Math.Min(e.Y, PictureBox.Height);

            Roi lastRoi = roiList[roiList.Count - 1];
            Roi lastCalibratedRoi = calibratedRoiList[calibratedRoiList.Count - 1];

            lastCalibratedRoi.Width = (int)(mouseX * WidthRatio) - lastCalibratedRoi.TopLeft.X;
            lastCalibratedRoi.Height = (int)(mouseY * HeightRatio) - lastCalibratedRoi.TopLeft.Y;

            lastRoi.Width = mouseX - lastRoi.TopLeft.X;
            lastRoi.Height = mouseY - lastRoi.TopLeft.Y;

        }

로직 자체는 빈틈이 없다 생각되어 C#의 구조체와 클래스의 어떠한 차이로 발생한 이슈가 아닌가 추측이 들었고,

해당 내용을 공부하니 원인을 찾을 수 있었다.

그림 출처: https://woozzang.tistory.com/29

즉 위에 그림기준으로 생각하면 원래 아래 존재하는 코드는 Heap 메모리의 주소를 받아 사용하여 값이 바뀌게되면 Call By Reference 참조의 의한 호출이기 때문에 실제 값 또한 바뀌었을 것 인대

Roi lastRoi = roiList[roiList.Count - 1];
Roi lastCalibratedRoi = calibratedRoiList[calibratedRoiList.Count - 1];

구조체로 바뀌게 되어 Stack 영역에는 실제 값이 저장되게 되어 Call By Value 값의 의한 호출이 되어 해당 값을 바뀌더라도 원본의 값이 변경되지 않게 되었다.

 

즉 List에 C# 클래스가 저장될 때는 참조를 저장하기 때문에 위에 코드에서 참조된 값을 수정하여도 아무 문제가 일어나지 않지만

C# 구조체가 저장될 때는 참조를 저장하는 것이 아닌 값을 저장하는 것이기 때문에 이러한 문제가 발생한 것 이었다.

<수정된 코드>

값을 직접 바꾸어 주도록 로직을 수정하였다.

        private void UpdateRoi(MouseEventArgs e, List<Roi> roiList, List<Roi> calibratedRoiList)
        {
            if (roiList.Count == 0) return;

            int mouseX = Math.Min(e.X, PictureBox.Width);
            int mouseY = Math.Min(e.Y, PictureBox.Height);

            Roi lastRoi = roiList[roiList.Count - 1];
            Roi lastCalibratedRoi = calibratedRoiList[calibratedRoiList.Count - 1];

            lastCalibratedRoi.Width = (int)(mouseX * WidthRatio) - lastCalibratedRoi.TopLeft.X;
            lastCalibratedRoi.Height = (int)(mouseY * HeightRatio) - lastCalibratedRoi.TopLeft.Y;

            lastRoi.Width = mouseX - lastRoi.TopLeft.X;
            lastRoi.Height = mouseY - lastRoi.TopLeft.Y;

            roiList[roiList.Count - 1] = lastRoi;
            calibratedRoiList[calibratedRoiList.Count - 1] = lastCalibratedRoi;
        }

'Project > Vision Inspection GUI' 카테고리의 다른 글

논문 초록 작성 고민  (1) 2023.07.31
C# OpenCVSharp4 Troble Shooting  (0) 2023.07.23

+ Recent posts