본문 바로가기
DEV/Web 개발

Web 개발 :: 딥러닝 이미지 처리(유화제작) 프로젝트 구현_TIL58

by 올커 2022. 11. 28.

■ JITHub 개발일지 58일차

□  TIL(Today I Learned) ::

DRF, 딥러닝_이미지 유화(Painting) 처리 및 게시글 생성

 1. 이미지 유화 게시글 생성 기능

  - 스타일 선택을 마무리하면 유화(게시글) 생성 페이지로 이동시켜야 한다. Front end에서는 StyleSelect시 아래와 같이 get method를 통해 스타일들을 가져온다. 이 때 response를 json 타입으로 받아오고, 이 json 파일을 forEach를 통해 하나하나 돌면서 아래와 같이 style-box에 넣어 반복시킨다. 이 때 스타일의 이미지와 이름을 ${item[x]}를 활용하여 불러오고, 또, 특정 스타일을 선택하면 'move_create_page()' 함수를 실행시킨다. 

//Style select
async function StyleSelectView(){
    const response = await fetch(`${backendBaseUrl}/paintings/style/`, {
        method: 'GET',
        headers: {
            "Content-type": "application/json",
            'Authorization': "Bearer " + localStorage.getItem("access")
        }
    })
    response_json = await response.json()

    $('#style-box').empty()
    response_json.forEach(item => {
        $('#style-box').append(
            `
            <div class="col-xxl-4 col-xl-4 col-lg-6 col-md-6 mb-6">
                <div class="explore-style-one">
                    <div class="thumb">
                    <a href="#" onclick="move_create_page(${item[0]-1})"><img src="./model_imgs/${item[1]}.png" alt="nft live auction thumbnail"></a>
                    <!-- End .reaction-count -->
                    </div>
                    <!-- End .thumb -->
                    <div class="content">
                    <div class="header d-flex-between pt-4 pb-3">
                        <h3 class="title"><a href="#" onclick="move_create_page(${item[0]-1})">${item[1]}</a></h3>
                    </div>
                    <!-- .header -->
                    <!-- End product-share-wrapper -->
                    
                </div>
            </div>
            `
        )
        
    });
}

function move_create_page(style_no){ 
    window.location.href = `/paint_create.html?$id=${style_no}/`
}

  - 이미지를 업로드할 때에는 아래 uploadImg() 함수를 호출한다. 이 때 위 코드의 마지막 줄을 살펴보면 url로 style_no를 넘겨주고 있기 때문에 location.href.split('=')[1][0]을 통해 style_no를 추출해내고, before_image에는 업로드된 이미지를 getElementById를 통해 가져온다. 이 2가지 정보는 POST를 통해 Backend에 보내어 DB에 저장하도록 한다. 

 - 이 코드에서 다르게 시도했던 점은 json파일을 formData를 정의하여 보내주고 있는 점이다. 전송된 결과는 크게 다르지 않았다. 그리고 Backend에서 전달받은 response에서 painting_id와 after_img 경로를 localStorage에 저장해둔다.

async function uploadImg() {
    let style_no = location.href.split('=')[1][0]
    style_no = Number(style_no)+1
    const before_image = document.getElementById("before_image").files[0]

    const formData = new FormData()
    formData.append("style", style_no)
    formData.append("before_image", before_image)

    // const context = {
    //     // "style" : style_no,
    //     "upload_img" : before_img
    // }
    const response = await fetch(`${backendBaseUrl}/paintings/img/`, {
        method: 'POST',
        headers: {
            'Authorization': "Bearer " + localStorage.getItem("access")
        },
        body: formData
    })
    const response_json = await response.json()


    localStorage.setItem("pt_id", response_json.id)
    localStorage.setItem("after_image", response_json.after_image)
    savePainting()
}

 - 최종적으로 그림을 저장할 때에는 위에서 가져온 Data를 토대로 DB에 저장해야 한다. 아래와 같이 저장하는데, user_id를 Owner, Author에 저장해야 했기 때문에 payload에서 가져오는 코드가 필요했다. 마찬가지로 DB에 저장해야 하는데 기존에 레코드가 존재하기 때문에 PUT 메서드로 Backend에 보내준다.

async function savePainting() {
    const painting_id = localStorage.getItem("pt_id")
    // const after_image = localStorage.getItem("after_image")
    const title = document.getElementById("title").value
    const content = document.getElementById("content").value

    let storage = localStorage.getItem('payload');
    const personObj = JSON.parse(storage);
    user_id = personObj['user_id'];

    const formData = new FormData()
    formData.append("painting_id", painting_id)
    formData.append("title", title)
    formData.append("content", content)
    formData.append("user_id", user_id)


    const response = await fetch(`${backendBaseUrl}/paintings/img/${painting_id}/`, {
        method: 'PUT',
        headers: {
            'Authorization': "Bearer " + localStorage.getItem("access")
        },
        body: formData
    })
    move_profile_page()
}

 - 이미지 업로드시 사용한 View 는 아래와 같다.

class ImageUploadView(APIView):
    permission_classes = [IsAuthenticated]

    #유화 스타일 생성 페이지
    @swagger_auto_schema(operation_summary="유화 스타일 생성", 
                        responses={ 200 : '성공', 500:'서버 에러'})
    def get(self, requets):
        style = [[x, y] for x, y in STYLE_CHOICES]
        return Response(style, status=status.HTTP_200_OK)
    
    #이미지 업로드(before -> after)
    @swagger_auto_schema(request_body=ImageSerializer, 
                        operation_summary="유화 이미지 업로드(before -> after)", 
                        responses={ 200 : '성공', 400:'인풋값 에러', 500:'서버 에러'})
    def post(self, request):
        serializer = ImageSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

 - 최종 게시물을 생성할 때는 아래와 같이 view를 구성했다.

class PaintingCreateView(APIView):
    permission_classes = [IsAuthenticated]
    
    #이미지 스타일 적용된 유화 생성(after)
    @swagger_auto_schema(request_body=PaintingCreateSerializer, 
                        operation_summary="이미지 스타일 적용된 유화 생성", 
                        responses={ 201 : '성공', 400:'인풋값 에러', 404:'찾을 수 없음', 500:'서버 에러'})
    def put(self, request, painting_id):
        painting = get_object_or_404(Painting, id=painting_id)
        serializer = PaintingCreateSerializer(painting, data=request.data)
        if serializer.is_valid():
            serializer.save(owner=request.user, author=request.user)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

 - 딥러닝 코드를 불러오기 위해서 PaintingCreateSerializer는 아래와 같이 구성했다. 각 모델에 필요한 필드들과 after_image에는 painting_styler 함수를 호출하여 처리된 유화 이미지 경로를 받아온다.

#유화 생성 serializer
class PaintingCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Painting
        fields = ('title', 'content', 'owner', 'author', 'after_image', )
        extra_kwargs = {'title': {
                        'error_messages': {
                        'required': '제목을 입력해주세요',
                        'blank':'제목을 입력해주세요',}},

                        'content':{
                        'error_messages': {
                        'required':'내용을 입력해주세요.',
                        'blank':'내용을 입력해주세요.',}},
                        }

    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.content = validated_data.get('content', instance.content)
        instance.owner = validated_data.get('user_id', validated_data["owner"])
        instance.author = validated_data.get('user_id', validated_data["author"])
        instance.after_image = painting_styler(instance.before_image, instance.style)
        
        instance.save()

        return instance

 

반응형

댓글