본문 바로가기
튜토리얼/p5js

p5.js로 구현하는 모자이크 효과 만들기

by 아트하는 개발자 2024. 5. 2.

이번 포스트에서는 p5.js를 사용하여 모자이크 효과를 만드는 방법에 대해 알아보겠습니다. 모자이크 효과는 이미지를 작은 타일로 분할하여 독특한 시각적 효과를 만들어내는 기술입니다. p5.js의 강력한 이미지 처리 기능을 활용하여 쉽게 모자이크 효과를 구현할 수 있습니다.

 

p5.js로 구현하는 모자이크 효과 만들기

 

p5.js로 구현하는 모자이크 효과 만들기

 

1. 이미지 로드 및 표시

2. 모자이크 효과 구현

3. 입력하기

4. 입력하기

추천글

위의 목차를 클릭하면 해당 글로 자동 이동 합니다.

 

이미지 로드 및 표시

p5.js에서 이미지를 로드하기 위해선 서버를 사용해야합니다. 인터넷 url주소를 사용하셔도 되지만 자신이 가지고 있는 사진을 이용하기 위해선 서버를 열어 놓아야 합니다. 그래서 간단히 파이썬 플라스크를 이용해서 만들어보겠습니다.

from flask import Flask, send_from_directory
from flask_cors import CORS

app = Flask(__name__)
CORS(app)  # 모든 경로에 대해 CORS 활성화

# 정적 파일을 제공하는 라우트
@app.route('/assets/<path:filename>')
def serve_assets(filename):
    return send_from_directory('assets', filename)

if __name__ == '__main__':
    app.run(debug=True)

모자이크 효과 구현

따로 코드를 나누지 않고 html에서 다 사용하는 방향으로 하겠습니다.

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/p5@1.9.3/lib/p5.js"></script>
    <title> p5js Image</title>
</head>
<body>
    <script>
        let img; // 변수 'img' 선언
        let mosaicSize = 20;
        let imgOrigin;

        function preload(){
            //img = loadImage('http://127.0.0.1:5000/assets/hen.jpg'); // 서버에서 이미지 불러올때
            img = loadImage('https://media.istockphoto.com/id/1496414074/ko/%EC%82%AC%EC%A7%84/%EC%95%84%EC%B9%A8%EC%97%90-%EC%9D%BC%EC%B6%9C-%ED%95%98%EB%8A%98%EA%B3%BC-%ED%95%A8%EA%BB%98-kawah-ijen-%ED%99%94%EC%82%B0%EC%9D%98-%EB%B6%84%ED%99%94%EA%B5%AC%EC%97%90-%EC%84%9C-%EC%9E%88%EB%8A%94-%EC%97%AC%ED%96%89%EC%9E%90-%EB%82%A8%EC%9E%90.jpg?s=1024x1024&w=is&k=20&c=-1AKj3iKKKdpCYyrovJGAxbhfKTtTzWDzqoNfQ_c1mI='); // 이미지 불러오기
            imgOrigin = img;
        }

        function setup() {
            createCanvas(2000, 2000);

            image(img, 0, 0 , img.width / 2, img.height / 2);
            loadPixels();

            // 각 영역의 평균 색상값을 계산하여 모자이크 효과 적용
            for (let y = 0; y < height; y += mosaicSize) {
              for (let x = 0; x < width; x += mosaicSize) {
                let sumR = 0, sumG = 0, sumB = 0;
                let count = 0;
                // 해당 영역의 픽셀들의 색상값을 합산
                for (let j = 0; j < mosaicSize; j++) {
                  for (let i = 0; i < mosaicSize; i++) {
                    let px = x + i;
                    let py = y + j;
                    // 캔버스 영역을 벗어나지 않도록 확인
                    if (px < width && py < height) {
                      let index = (px + py * width) * 4;
                      sumR += pixels[index];
                      sumG += pixels[index + 1];
                      sumB += pixels[index + 2];
                      count++;
                    }
                  }
                }
                // 평균 색상값 계산
                let avgR = sumR / count;
                let avgG = sumG / count;
                let avgB = sumB / count;
                // 해당 영역의 모든 픽셀을 평균 색상값으로 설정
                for (let j = 0; j < mosaicSize; j++) {
                  for (let i = 0; i < mosaicSize; i++) {
                    let px = x + i;
                    let py = y + j;
                    // 캔버스 영역을 벗어나지 않도록 확인
                    if (px < width && py < height) {
                      let index = (px + py * width) * 4;
                      pixels[index] = avgR;
                      pixels[index + 1] = avgG;
                      pixels[index + 2] = avgB;
                    }
                  }
                }
              }
            }
            updatePixels(); // 변경된 픽셀을 적용
        }
        function draw(){
            image(imgOrigin, img.width / 2, 0 , imgOrigin.width / 2, imgOrigin.height / 2);
            
        }
    </script>
</body>
</html>

 

각각 나눠서 설명을 드리도록 하겠습니다.

 

아래 코드는 이미지를 mosaicSize로 지정된 크기의 작은 영역으로 나누기 위한 중첩 반복문입니다. sumR, sumG, sumB는 각 영역 내 픽셀들의 RGB 색상값을 합산하기 위한 변수이며, count는 해당 영역 내 픽셀 수를 세기 위한 변수입니다.

for (let y = 0; y < height; y += mosaicSize) {
  for (let x = 0; x < width; x += mosaicSize) {
    let sumR = 0, sumG = 0, sumB = 0;
    let count = 0;

 

현재 영역 내의 각 픽셀에 대해 RGB 색상값을 합산하는 중첩 반복문입니다. px와 py는 현재 픽셀의 x, y 좌표를 나타내며, index는 pixels 배열에서 해당 픽셀의 색상값이 저장된 인덱스를 계산합니다. 그런 다음 sumR, sumG, sumB에 각각의 색상값을 더하고, count를 증가시킵니다. 이때 캔버스 영역을 벗어나는 픽셀은 건너뜁니다.

    for (let j = 0; j < mosaicSize; j++) {
      for (let i = 0; i < mosaicSize; i++) {
        let px = x + i;
        let py = y + j;
        // 캔버스 영역을 벗어나지 않도록 확인
        if (px < width && py < height) {
          let index = (px + py * width) * 4;
          sumR += pixels[index];
          sumG += pixels[index + 1];
          sumB += pixels[index + 2];
          count++;
        }
      }
    }

 

이 부분에서는 현재 영역 내 픽셀들의 평균 RGB 색상값을 계산합니다. 각 색상값의 합을 픽셀 수로 나누어 평균값을 구합니다.

    let avgR = sumR / count;
    let avgG = sumG / count;
    let avgB = sumB / count;

 

여기는 현재 영역 내의 모든 픽셀에 대해 앞서 계산한 평균 RGB 색상값을 할당합니다. 이렇게 하면 해당 영역 내의 모든 픽셀이 동일한 색상값을 가지게 되어 모자이크 효과가 생깁니다. 이때도 캔버스 영역을 벗어나는 픽셀은 건너뜁니다.

    for (let j = 0; j < mosaicSize; j++) {
      for (let i = 0; i < mosaicSize; i++) {
        let px = x + i;
        let py = y + j;
        // 캔버스 영역을 벗어나지 않도록 확인
        if (px < width && py < height) {
          let index = (px + py * width) * 4;
          pixels[index] = avgR;
          pixels[index + 1] = avgG;
          pixels[index + 2] = avgB;
        }
      }
    }
  }
}

 

 

이 코드는 실제로 되는 코드가 안올라가네요... 아마 이미지를 불러오는 부분이 있어서 막히는게 있는것 같습니다. ㅠ

 

이렇게 p5js를 사용해서 모자이크 효과를 만들어보았습니다. 이 과정은 OpenCV와도 비슷합니다. OpenCV를 하셨던 분들이라면 좀 더 쉽게 하실 수 있을 겁니다. 다음에 해볼 내용이나 해줬으면 하는 내용이 있다면 알려주세요! 

 

추천글

디지털 아트의 세계로 첫발을 내딛다: p5.js로 시작하는 창의적 여정

 

디지털 아트의 세계로 첫발을 내딛다: p5.js로 시작하는 창의적 여정

이번 포스트에서는 웹 기반의 크리에이티브 코딩 라이브러리인 p5.js에 대해 소개하고, 이를 시작하게 된 계기와 기본 개념에 대해 이야기할 것입니다. p5.js가 어떻게 예술가, 디

creativecodingart.tistory.com

초보자도 쉽게 따라할 수 있는 웹 기반 GLSL 쉐이더 프로그래밍

 

초보자도 쉽게 따라할 수 있는 웹 기반 GLSL 쉐이더 프로그래밍

웹에서 GLSL(OpenGL Shading Language)을 사용하여 쉐이더 프로그래밍을 실습하고 실험할 수 있는 다양한 플랫폼이 있지만, 그중에서도 특히 주목할 만한 사이트가 있습니다. 바로 'ShaderToy'와 'GLSL Editor'

creativecodingart.tistory.com

 

반응형