no image
JWT(JSON Web Tokens)에 대해서 알아보자
JWT는 Json Web Token의 약자로 일반적으로 클라이언트와 서버 사이에서 통신할 때 권한을 위해 사용하는 토큰이다. 토큰을 발급 받고 매 통신마다 토큰 인증에 성공해야만 JSON 통신이 가능함. 1. JWT의 구조 JWT의 구조는 Header, Payload Signature 세 가지로 구성되어 있다. 각각의 제외한 JSON 부분들은 하나의 데이터로 표현될 때 Base64로 인코딩되어 표현된다. Header { "alg": "HS256", "typ": "JWT" } alg ⇒ JWT 구조에서 Signature에는 Header와 Payload가 합쳐져 특정 알고리즘으로 암호화가 진행이 된 다음에 만들어지는데, 그 때 사용되는 알고리즘이다. "alg": "HS256" 는 Signature 부분을 H..
2024.02.22
no image
[OpenCV] 이미지의 특정 위치 좌표 추출
OpenCV로 이미지의 원하는 위치의 좌표 추출하는 법을 알아보자 좌표를 추출하여 해당 위치의 이미지 색상을 바꾸는 등의 응용까지 해볼 수 있다. 해당 이미지를 가지고 현재 회색인 신체 윤곽선 부분을 초록색으로 바꿔보자 1. 윤곽선 이미지 불러오기 import cv2 person = cv2.imread('person.png') 검은색 배경에 회식 라인의 윤곽선 이미지다. 2. 이미지 회색 처리 gray = cv2.cvtColor(resized_person, cv2.COLOR_BGR2GRAY) cv2.imshow('result', gray) cv2.waitKey(0) cv2.destroyAllWindows() 해당 이미지의 좌표를 추출하기 위해 이미지 이진화 작업이 꼭 필요한데 그 전에 회색 처리를 먼저 ..
2024.02.21
no image
[OpenCV] 이미지 합성
OpenCV로 이미지 끼리 합성을 하는 방법을 알아보자. 이미지 합성을 하기 위해서는 OpenCV에서 제공하는 비트 연산 기능을 이용하면 된다. 비트 연산 기능을 이용하여 배경 사진에 특정 로고 사진을 합성해보자 1. 로고 이미지 이진화 img_logo = cv2.imread('logo.png') img_gray = cv2.cvtColor(img_logo, cv2.COLOR_BGR2GRAY) # 이진화 전 회색 처리 필수 ret, img_mask = cv2.threshold(img_gray, 200, 255, cv2.THRESH_BINARY) img_mask_inv = cv2.bitwise_not(img_mask) cv2.imshow('img_mask', img_mask) cv2.imshow('img_m..
2024.02.08
no image
[OpenCV] 이미지 윤곽선 검출
사람의 인체 모양을 인식하고 어떠한 판단을 내리기 위해서는 신체에 윤곽선을 그리고, 해당 윤곽선에 대한 좌표 데이터를 획득해야 한다. 이러한 목표를 성취하기 위해서 첫 번째로 해야 할 작업은 이미지 안에 특정 사물의 윤곽선을 그리는 것부터 시작한다. 이 글은 파이썬의 이미지 처리 라이브러리인 OpenCV를 통해서 이미지 내 윤곽선을 검출하는 방법을 기술한다. 앞서 작성한 OpenCV의 설명을 보자면 OpenCV는 이미지를 흑백으로 변경을 하거나 이미지의 특정 위치의 좌표값을 얻는 등 여러 처리를 할 수 있는 라이브러리다. 해당 라이브러리를 사용하여 윤곽선을 검출하기 위해 과정을 단계별로 나누자면 이미지의 윤곽선을 검출하는 과정 이미지 회색 처리 이미지 바이너리 처리 위 모든 과정을 거친 이미지의 윤곽선 ..
2024.02.07
[Flutter] Flutter 웹 소켓 클라이언트 구축
통신 방식 자체가 웹 소켓이라는 것이 일반 HTTP 통신과는 차이점이 있기 때문에 서버 뿐만 아니라 클라이언트도 웹 소켓의 특성을 적용해야 한다. 플러터로 웹 소켓 통신 방식을 활용하기 위한 클라이언트 구축하는 방법을 알아보자 1. SocketIO 패키지 설치 dependencies: socket_io_client: pubspec.yml 에 넣어주고 flutter pub get 실행 2. 해당 패키지 임포트 import 'package:socket_io_client/socket_io_client.dart' as IO; 3. 웹 소켓 연결 설정 final IO.Socket socket = IO.io('', IO.OptionBuilder().setTransports(['websocket']) .build()..
2024.02.05
[Flask] Flask 웹 소켓 서버 구축
웹 소켓이란? 본래 서버와 클라이언트가 통신하기 위해서는 HTTP 통신을 통해 클라이언트의 요청과 서버의 응답 형식으로 통신이 이루어진다. HTTP 통신은 무조건 클라이언트의 요청이 있어야 서버에서 데이터를 송신할 수 있는데, 이 과정이 이루어지고 나면 클라이언트와 서버 간의 연결이 종료된다. 이를 개선하여 클라이언트와 서버의 연결을 유지하면서 서로 원할 때마다 데이터를 송수신 하기 위해 등장한 것이 웹 소켓이다. 1. SocketIO 라이브러리 설치 pip install flask-socketio 에디터 터미널에 입력해준다. 2. 해당 라이브러리 임포트 from flask_socketio import SocketIO 3. Flask 서버에 웹 소켓 서버 적용 app = Flask(__name__) so..
2024.02.05
[Flutter] WebView로 앱 내에 웹사이트 출력
플러터 WebView를 이용하여 앱 내에 웹사이트를 표출할 수 있다. 1. WebView 관련 패키지 의존성 추가 dependencies: webview_flutter: webview_flutter_android: webview_flutter_wkwebview: pubspec.yaml에 입력하고 flutter pub get 실행 2. 해당 패키지 임포트 import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter_android/webview_flutter_android.dart'; import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'..
2024.02.01
[Flask] Flask 서버를 이용한 카메라 웹 스트리밍
파이썬의 OpenCV를 이용한 카메라를 웹에 표출하기 위해서는 Flask 서버를 구축해야 한다. 1. Flask 설치 pip install Flask Flask를 설치하기 위해 해당 명령어를 입력한다. 2. 라이브러리 Import from flask import Flask, Response, render_template import cv2 Flask를 포함하여 여러 라이브러리를 임포트한다. 3. 카메라 표출 함수 생성 camera = cv2.VideoCapture(0) def generate_frames(): while True: success, frame = camera.read() # 프레임 읽기 if not success: break else: ret, buffer = cv2.imencode('.j..
2024.02.01
728x90

JWT는 Json Web Token의 약자로 일반적으로 클라이언트와 서버 사이에서 통신할 때 권한을 위해 사용하는 토큰이다. 토큰을 발급 받고 매 통신마다 토큰 인증에 성공해야만 JSON 통신이 가능함.

 

 

1. JWT의 구조

  • JWT의 구조는 Header, Payload Signature 세 가지로 구성되어 있다.
  • 각각의 제외한 JSON 부분들은 하나의 데이터로 표현될 때 Base64로 인코딩되어 표현된다.

 

Header   

{ 
   "alg": "HS256",
   "typ": "JWT"
 }

 

    • alg ⇒ JWT 구조에서 Signature에는 Header와 Payload가 합쳐져 특정 알고리즘으로 암호화가 진행이 된 다음에 만들어지는데, 그 때 사용되는 알고리즘이다. "alg": "HS256" 는 Signature 부분을 HS256 알고리즘으로 암호화 되었다는 뜻이다.
    • typ ⇒ 토큰의 유형이다. JWT 토큰을 사용한다.

 

Payload

{
  "sub": "1234567890",
  "lat": 1516239022
}

 

    • Payload(페이로드)에는 사용자의 인증 정보가 담긴다. 여기에 담기는 정보의 조각 단위를 Claim이라 불린다.
    • Claim에는 등록된 클레임, 공개 클레임, 비공개 클레임 3가지 종류가 있는데 자주 사용되는 것은 등록된 클레임이다.
    • iss ⇒ 토큰 발급자(issuer)
    • sub ⇒ 토큰 제목(subject) 주로 사용자 이메일 사용한다.
    • aud ⇒ 토큰 대상자(audience)
    • exp ⇒ 토큰 만료 시간(expiration)
    • nbf ⇒ 토큰 활성 날짜(not before)
    • iat ⇒ 토큰 발급 경과 시간(issued at) 토큰 발급 이후의 경과 시간
    • jti ⇒ JWT 토큰 식별자(JWT ID) 중복 방지를 위해 사용한다.

 

Signature

  • Signature(서명)은 헤더와 페이로드가 합쳐져 암호화 후에 담겨져 있는 데이터다.
    1. 헤더(Header)와 페이로드(Payload)의 값을 각각 BASE64로 인코딩
    2. 인코딩한 헤더(Header)에서 정의한 알고리즘으로 암호화
    3. 암호화한 값을 다시 BASE64로 인코딩하여 생성

 

 

2. JWT 응용 원리

  1. 사용자가 아이디와 비밀번호를 입력하고 로그인을 요청
  2. DB 내 아이디 비밀번호 데이터와 일치하는지 확인
  3. 해당 사용자 정보를 기반으로 JWT 토큰 발급
  4. 응답 헤더에 해당 토큰을 추가하여 클라이언트로 전송하고 클라이언트는 이를 저장
  5. 이후 JSON 통신을 할 때마다 서버로 토큰을 요청 헤더에 추가하여 전송
  6. 서버에서 해당 토큰을 검증
  7. 검증이 완료되면 요청 데이터를 응답
728x90
728x90

OpenCV로 이미지의 원하는 위치의 좌표 추출하는 법을 알아보자

좌표를 추출하여 해당 위치의 이미지 색상을 바꾸는 등의 응용까지 해볼 수 있다.

해당 이미지를 가지고 현재 회색인 신체 윤곽선 부분을 초록색으로 바꿔보자

 

1. 윤곽선 이미지 불러오기

import cv2

person = cv2.imread('person.png')
  • 검은색 배경에 회식 라인의 윤곽선 이미지다.

 

 

2. 이미지 회색 처리

gray = cv2.cvtColor(resized_person, cv2.COLOR_BGR2GRAY)

cv2.imshow('result', gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 해당 이미지의 좌표를 추출하기 위해 이미지 이진화 작업이 꼭 필요한데 그 전에 회색 처리를 먼저 확실하게 해준다.

 

 

3. 이미지 이진화

ret, otsu = cv2.threshold(gray, -1, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

cv2.imshow('result', otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 오츠 알고리즘을 통해 자동으로 이미지 이진화를 진행한다.

  • 좌표 추출을 원하는 위치가 검정색(픽셀 값: 0)이 되어야 한다. cv2.bitwise_not(otsu) 를 실행하여 반전 이진화를 진행한다.

 

 

4. 해당 윤곽선 좌표 추출

import numpy as np
np.where(contour == 0)
  • np.where() 는 Numpy 자료형 array 에 특정 조건을 만족하는 위치의 인덱스를 가져올 수가 있다.

  • 이미지를 OpenCV로 불러오게 되면 Numpy 자료형으로 불러오게 된다.

 

 

5. 회색 이미지에서 컬러 이미지로 변환

contour_color = cv2.cvtColor(contour, cv2.COLOR_GRAY2BGR)
  • 이미지를 가지고 회색 처리나 이진화를 하게 되면 색상 값이 하나만 존재하게 된다.
  • 이미지는 Numpy 자료형이기 때문에 배열로 치자면 컬러는 R,G,B 3가지의 색상 값을 가지고 있기 때문에 3차원 배열이고, 무채색 이미지는 검은색 계열 한가지의 색상만 존재하기 때문에 2차원 배열이다.

  • 따라서, 컬러 이미지로 변환을 해주면 2차원에서 3차원으로 변환된다.

  • 이미지의 검색 부분을 초록색으로 변경해줄 것이기 때문에 이와 같이 컬러 이미지로 변환한다.

 

 

6. 이미지 내 검정색 부분 초록색으로 변환

contour_color[np.where(contour == 0)] = [0,255,0] 
# 검은색=[0,0,0] 초록색=[0,255,0]
  • np.where(contour==0) 를 통해 윤곽선 이미지의 검은색 부분을 찾는다.
  • contour_color[np.where(contour == 0)] = [0,255,0] 컬러로 변환된 이미지에 찾은 좌표를 매칭시켜 초록색 RGB값을 삽입한다.

※ 결과

728x90

[OpenCV] 이미지 합성

태이니즘
|2024. 2. 8. 18:04
728x90

OpenCV로 이미지 끼리 합성을 하는 방법을 알아보자.

이미지 합성을 하기 위해서는 OpenCV에서 제공하는 비트 연산 기능을 이용하면 된다.

비트 연산 기능을 이용하여 배경 사진에 특정 로고 사진을 합성해보자

배경 이미지
로고 이미지

 

 

1. 로고 이미지 이진화

img_logo = cv2.imread('logo.png')
img_gray = cv2.cvtColor(img_logo, cv2.COLOR_BGR2GRAY) # 이진화 전 회색 처리 필수
ret, img_mask = cv2.threshold(img_gray, 200, 255, cv2.THRESH_BINARY)
img_mask_inv = cv2.bitwise_not(img_mask)
cv2.imshow('img_mask', img_mask)
cv2.imshow('img_mask_inv', img_mask_inv)
cv2.waitKey()
cv2.destroyAllWindows()
  • cv.threshold(img_gray, 200, 255, cv.THRESH_BINARY)를 사용하여 이진화를 진행한다. 해당 코드를 보면 픽셀이 200을 넘는 부분은 흰색인 배경만 존재하기 때문에 배경을 제외하고는 검은색으로 변환 될 것이다. *** 흰색 픽셀: 255, 검정색 픽셀: 0**
  • img_mask_inv = cv2.bitwise_not(img_mask) 는 위 바이너리 이미지를 반전 시키는 코드이다. 해당 이미지도 이미지 합성 시에 꼭 필요하다.

 

 

2. 로고 이미지 크기로 배경 이미지 잘라내기

img_background = cv2.imread('background.png')
height, width = img_logo.shape[:2]
img_roi = img_background[0:height, 0:width]
cv2.imshow('imgroi', img_roi)
cv2.waitKey()
cv2.destroyAllWindows()
  • 로고 이미지를 배경 이미지의 원하는 위치에 삽입을 하려면 해당 부분의 로고 이미지 크기 만큼 잘라낸다.
  • 잘라낸 배경 이미지에 로고 이미지와 비트 연산을 진행해야 한다.

 

 

3. 로고 이미지와 배경 이미지 합성 연산

img1 = cv2.bitwise_and(img_logo, img_logo, mask = img_mask_inv) 
img2 = cv2.bitwise_and(img_roi, img_roi, mask=img_mask)
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.waitKey()
cv2.destroyAllWindows()
  • cv2.bitwise_and(img_logo, img_logo, mask = img_mask_inv) 를 통해 로고 이미지 및 배경 이미지와 앞서 이진화를 진행한 바이너리 이미지와 AND 연산한다.

합성할 로고 이미지
합설할 배경 이미지

  • 위 AND 연산 결과로 나온 로고 이미지(img1)와 배경 이미지(img2) 자체를 더한다.
dst = cv2.add(img1, img2)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

 

 

4. 합성이 완료된 이미지 원본 이미지에 덮어 씌우기

img_background[0:height, 0:width] = dst
cv2.imshow('result', img_background)
cv2.waitKey()
cv2.destroyAllWindows()
  • 합성이 완료된 이미지 부분을 원본 이미지의 부분과 일치 시켜 덮어 씌운다.

※ 결과

728x90
728x90

사람의 인체 모양을 인식하고 어떠한 판단을 내리기 위해서는 신체에 윤곽선을 그리고, 해당 윤곽선에 대한 좌표 데이터를 획득해야 한다.

 

이러한 목표를 성취하기 위해서 첫 번째로 해야 할 작업은 이미지 안에 특정 사물의 윤곽선을 그리는 것부터 시작한다.

 

이 글은 파이썬의 이미지 처리 라이브러리인 OpenCV를 통해서 이미지 내 윤곽선을 검출하는 방법을 기술한다.

 

앞서 작성한 OpenCV의 설명을 보자면 OpenCV는 이미지를 흑백으로 변경을 하거나 이미지의 특정 위치의 좌표값을 얻는 등 여러 처리를 할 수 있는 라이브러리다.

 

해당 라이브러리를 사용하여 윤곽선을 검출하기 위해 과정을 단계별로 나누자면

  • 이미지의 윤곽선을 검출하는 과정
    1. 이미지 회색 처리
    2. 이미지 바이너리 처리
    3. 위 모든 과정을 거친 이미지의 윤곽선 검출
    4. 해당 윤곽선 이미지에 그리기

위와 같은 단계를 거친다.

 

1. 이미지 회색 처리

img = cv2.imread('card.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  • cv2.cvtColor() 는 이미지를 특정 색상으로 변환해준다.
  • 첫 번째 파라미터로 이미지를 삽입하고 두 번째 파라미터로 색상 변환 방법을 삽입한다.
  • cv2.COLOR_BGR2GRAY 는 기존 BGR 방식의 색상에서 회색계열로 이미지를 변환한다는 의미이다.

 

 

2. 이미지 바이너리 처리

ret, otsu = cv2.threshold(gray, -1, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
  • 이미지를 바이너리(이진화) 시키면 픽셀 값은 0과 255만 갖게 할 수 있기 때문에 흰색과 검은색만 존재하게 할 수 있다.
  • 흰색과 검은색만 이루어진 이미지를 윤곽선 검출하기가 수월하기 때문에 이 과정을 꼭 거쳐야 한다.
  • cv2.threshold() 함수는 여러 개의 숫자 값을 특정한 임계값을 기준으로 두 가지 값으로 나누어 정의하는 함수이다.
  • cv2.threshold(image, threshold, value, type_flag)

      => image: 변환할 이미지, 이미지가 픽셀 값으로 변환되어 들어간다.

      => threshold: 임계값, 우리는 해당 임계값을 오츠 알고리즘이라는 것을 이용하여 자동으로 탐색할 것이기 때문에

            -1을 넣어주면 된다.

      => value: threshold에 기입한 임계값의 특정 조건에 만족하면 변환할 값

      => type_flag: 이진화 적용 방법, cv2.THRESH_BINARY는 픽셀 값이 임계값을 넘으면 value로 지정하고,

           넘지 못하면 0으로 지정하는 방법이다.

           해당 파라미터로 OR 조건으로 cv2.THRESH_OTSU 도 함께 기입할 시 오츠 알고리즘이 적용된다.

  • 오츠 알고리즘이란?

      => 이미지의 픽셀을 보고 이미지의 색상이 두 부류로 나뉘었을 때

            그림의 명암 분포가 가장 균일할 때의 임계값을 자동으로 계산하여 선택하는 알고리즘이다.

 

 

3. 위 모든 과정을 거친 이미지의 윤곽선 검출

contours, hierarchy = cv2.findContours(otsu, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
  • 앞서 변환한 바이너리 이미지에 대해 윤곽선을 검출한다.
  • contours 에 검출한 윤곽선의 좌표값들이 들어가기에, 윤곽선에 대한 작업 진행 시 이 변수를 적극 활용하면 된다.
  • cv2.findContours(image, mode, method)

      => image: 입력 이미지

      => mode: 윤곽선 검출 모드

        - cv2.RETR_EXTERNAL : 가장 외곽의 윤곽선만 찾음

        - cv2.PETR_LIST : 모든 윤곽선 찾음

      => method: 윤곽선 좌표값 반환 방법

        - APPROX_NONE: 윤곽선의 모든 좌표를 반환

        - APPROX_SIMPLE: 윤곽선의 꼭짓점 좌표만 반환

        - 윤곽선이 단순한 경우, 예를 들어 사각형인 경우에는 APPROX_SIMPLE을 사용하는 것이 메모리 성능에도

          효율적일 것이다.

 

 

4. 해당 윤곽선 이미지에 그리기

COLOR = (0, 200, 0) # 녹색
cv2.drawContours(img, contours, -1, COLOR, 2)
# cv2.drawContours(이미지, 윤곽선 정보, 인덱스, 색상, 두께)
# 인덱스가 -1이면 전체
  • 초록색에 두께 2로 전체 윤곽선을 이미지에 그린다.

 

※ 결과

728x90
728x90

통신 방식 자체가 웹 소켓이라는 것이 일반 HTTP 통신과는 차이점이 있기 때문에 서버 뿐만 아니라 클라이언트도 웹 소켓의 특성을 적용해야 한다.

플러터로 웹 소켓 통신 방식을 활용하기 위한 클라이언트 구축하는 방법을 알아보자

 

1. SocketIO 패키지 설치

dependencies:
  socket_io_client:
  • pubspec.yml 에 넣어주고 flutter pub get 실행

 

2. 해당 패키지 임포트

import 'package:socket_io_client/socket_io_client.dart' as IO;

 

 

3. 웹 소켓 연결 설정

final IO.Socket socket = IO.io('<http://10.0.2.2:5000>',
      IO.OptionBuilder().setTransports(['websocket'])
          .build());
  • 해당 패키지를 이용하여 웹 소켓이 적용된 서버의 아이피를 적는 등의 설정과 동시에 State를 생성한다.

 

4. 웹 소켓 서버 연결

@override
  void initState() {
    super.initState();
    socket.connect(); // 서버 연결
    setSocketEvent();
  }
  • socket.connect() 함수를 initState() 함수 안에 넣어서 해당 위젯이 실행될 때 연결이 실행되도록 한다.

 

5. 데이터를 송수신하는 방법

socket.emit('sendEventName', data) # 데이터 송신

socket.on('receiveEventName', (data) { # 데이터 수신
      print('받은 데이터: ' + data);
    });
  • 서버와 데이터를 송수신하기 위해서는 각 작업이 이루어지는 이벤트 이름을 서버와 통일한다.
  • 첫 번째 파라미터에는 그에 해당하는 이벤트 이름을 적고, 두 번째 파라미터에는 보내거나 받는 데이터가 사용된다.
728x90
728x90

웹 소켓이란?

  • 본래 서버와 클라이언트가 통신하기 위해서는 HTTP 통신을 통해 클라이언트의 요청과 서버의 응답 형식으로 통신이 이루어진다.
  • HTTP 통신은 무조건 클라이언트의 요청이 있어야 서버에서 데이터를 송신할 수 있는데, 이 과정이 이루어지고 나면 클라이언트와 서버 간의 연결이 종료된다.
  • 이를 개선하여 클라이언트와 서버의 연결을 유지하면서 서로 원할 때마다 데이터를 송수신 하기 위해 등장한 것이 웹 소켓이다.

 

1. SocketIO 라이브러리 설치

pip install flask-socketio
  • 에디터 터미널에 입력해준다.

 

2. 해당 라이브러리 임포트

from flask_socketio import SocketIO

 

 

3. Flask 서버에 웹 소켓 서버 적용

app = Flask(__name__)
socketio = SocketIO(app)
  • 변수로 생성한 Flask 객체를 SocketIO 생성자에 삽입하여 웹 소켓 서버로 적용한다.

 

4. 서버 실행

socketio.run(app, port=5000, debug=True)
  • 기존 Flask 서버를 실행할 때는 app.run() 함수를 실행시켰지만, 웹소켓을 적용한 서버를 실행할 때는 socketio.run() 함수를 실행한다.

 

5. 데이터를 송수신하는 방법

socketio.emit('sendEventName', data) # 데이터 송신

@socketio.on('receiveEventName') # 데이터 수신
def handle_message(data):
    print('받은 데이터: {}'.format(data))
  • 클라이언트와 데이터를 송수신하기 위해서는 각 작업이 이루어지는 이벤트 이름을 클라이언트와 통일한다.
  • 첫 번째 파라미터에는 그에 해당하는 이벤트 이름을 적고, 두 번째 파라미터에는 보내거나 받는 데이터가 사용된다.
728x90

'Python > Flask' 카테고리의 다른 글

[Flask] Flask 서버를 이용한 카메라 웹 스트리밍  (0) 2024.02.01
728x90

플러터 WebView를 이용하여 앱 내에 웹사이트를 표출할 수 있다.

 

1. WebView 관련 패키지 의존성 추가

dependencies:
  webview_flutter:
  webview_flutter_android:
  webview_flutter_wkwebview:
  • pubspec.yaml에 입력하고 flutter pub get 실행

 

2. 해당 패키지 임포트

import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';

 

 

3. Android 최소 SDK 버전 설정

android {
        defaultConfig {
            minSdkVersion 19
        }
    }
  • WebView 패키지는 안드로이드 SDK의 버전 19 이상부터 지원을 하기 때문에 설정을 해주기 위해 build.gradle 파일에서 작성한다.

 

4. WebView 컨트롤러 변수 선언

class _TrainingInState extends State<TrainingIn> {
  late final WebViewController _controller;
  • 웹뷰를 구현할 위젯에서 컨트롤러 State를 추가한다.

 

5. WebView 컨트롤러 초기 설정 코드 작성

@override
  void initState() {
    super.initState();
 
    late final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }
 
    final WebViewController controller =
        WebViewController.fromPlatformCreationParams(params);
 
    controller
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            debugPrint('WebView is loading (progress : $progress%)');
          },
          onPageStarted: (String url) {
            debugPrint('Page started loading: $url');
          },
          onPageFinished: (String url) {
            debugPrint('Page finished loading: $url');
          },
          onWebResourceError: (WebResourceError error) {
            debugPrint('''
              Page resource error:
                code: ${error.errorCode}
                description: ${error.description}
                errorType: ${error.errorType}
                isForMainFrame: ${error.isForMainFrame}
          ''');
          },
          onNavigationRequest: (NavigationRequest request) {
            debugPrint('allowing navigation to ${request.url}');
            return NavigationDecision.navigate;
          },
        ),
      )
      ..addJavaScriptChannel(
        'Toaster',
        onMessageReceived: (JavaScriptMessage message) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text(message.message)),
          );
        },
      )
      ..loadRequest(Uri.parse('10.0.2.2:5000/cameraPage'));
 
    if (controller.platform is AndroidWebViewController) {
      AndroidWebViewController.enableDebugging(true);
      (controller.platform as AndroidWebViewController)
          .setMediaPlaybackRequiresUserGesture(false);
    }
 
    _controller = controller;
  }
  • 웹뷰를 활용하기 위해 앞서 선언한 WebViewController를 이용하여 초기 설정을 진행한다.
  • ..loadRequest(Uri.parse('<https://flutter.dev/>')); 해당 코드로 앱 내에 출력하기 원하는 웹사이트 주소를 입력한다.

 

6. 설정된 컨트롤러를 이용하여 앱 내에 최종 표출

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: WebViewWidget(controller: _controller),
		)
	}
  • 최종적으로 웹사이트를 앱에 넣기 위해서 웹뷰를 구현할 위젯에 WebViewWidget 위젯을 사용한다. 앞서 설정한 컨트롤러 변수를 파라미터도 같이 넣어준다.
728x90
728x90

파이썬의 OpenCV를 이용한 카메라를 웹에 표출하기 위해서는 Flask 서버를 구축해야 한다.

 

1. Flask 설치

pip install Flask
  • Flask를 설치하기 위해 해당 명령어를 입력한다.

 

2. 라이브러리 Import

from flask import Flask, Response, render_template
import cv2
  • Flask를 포함하여 여러 라이브러리를 임포트한다.

 

3. 카메라 표출 함수 생성

camera = cv2.VideoCapture(0)
def generate_frames():
    while True:
        success, frame = camera.read()  # 프레임 읽기
        if not success:
            break
        else:
            ret, buffer = cv2.imencode('.jpg', frame)
            frame = buffer.tobytes()
            yield (b'--frame\\r\\n'
                   b'Content-Type: image/jpeg\\r\\n\\r\\n' + frame + b'\\r\\n')  # 프레임 스트리밍
  • 카메라 영상의 프레임 단위 이미지를 반환해주는 함수를 작성한다.
  • 일단 IP 카메라가 존재하지 않아서 camera = cv2.VideoCapture(0)을 통해 웹캠을 불러온다.

 

4. 카메라 표출 함수 실행 매핑 작성

@app.route('/camera')
def getCamera():
    return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
  • 카메라 프레임을 반환해주는 매핑 함수를 작성한다.
  • 해당 함수는 html 내에서 이용하면 된다.

 

5. 카메라 표출 페이지 출력 매핑 작성

@app.route('/cameraPage')
def cameraPage():
    return render_template('cameraPage.html')
  • 카메라 영상을 보여줄 페이지를 렌더링는 매핑을 작성한다.

 

6. 카메라를 최종적으로 출력하는 HTML 작성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Camera</title>
</head>
<body>
    <div>
        <img src="/camera" style="height:100vh; width: 100%"/>
    </div>
</body>
</html>
  • <img src="/camera" style="height:100vh; width: 100%"/> 해당 코드를 통해 Flask 내 카메라 표출 함수를 이용하여 최종적으로 카메라를 표출한다.

 

※ 전체 코드

from flask import Flask, Response, render_template
import cv2

app = Flask(__name__)
camera = cv2.VideoCapture(0)  # 웹캠에 연결

@app.route('/')
@app.route('/home')
def home():
    return '메인 페이지'

def generate_frames():
    while True:
        success, frame = camera.read()  # 프레임 읽기
        if not success:
            break
        else:
            ret, buffer = cv2.imencode('.jpg', frame)
            frame = buffer.tobytes()
            yield (b'--frame\\r\\n'
                   b'Content-Type: image/jpeg\\r\\n\\r\\n' + frame + b'\\r\\n')  # 프레임 스트리밍

@app.route('/cameraPage')
def cameraPage():
    return render_template('cameraPage.html')

@app.route('/camera')
def getCamera():
    return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Camera</title>
</head>
<body>
    <div>
        <img src="/camera" style="height:100vh; width: 100%"/>
    </div>
</body>
</html>
728x90

'Python > Flask' 카테고리의 다른 글

[Flask] Flask 웹 소켓 서버 구축  (0) 2024.02.05