Python-OpenCV 튜 토리 얼 이미지 의 비트 연산 상세 설명

8844 단어 PythonOpenCV이미지
1.위치 에 따라 반 bitwisenot()
비트 에 따라 반 을 취 하 는 것 은 수 치 를 각 bit 비트 에 따라 0,0 으로 1 로 바 꾸 는 것 이다.예 를 들 어 0xf 0 은 비트 에 따라 반 을 취하 면 0x0f 가 되 고 uint 8 유형의 데이터 라면 반 전후의 데 이 터 를 취하 여 결 과 를 0xff(255)로 추가 하 는 것 이다.다음 예 는 lena.jpg 와 opencv-logo.png 를 각각 위치 에 따라 반대 합 니 다.

import cv2

print('cv2.__version__:',cv2.__version__)
 
img1 = cv2.imread('..\\lena.jpg') 
img2 = cv2.imread('..\\opencv-logo.png' ) 
 
img_ret1 = cv2.bitwise_not(img1)
print('img1[161,199]:    ',img1[161,199])
print('img_ret1[161,199]:',img_ret1[161,199])
cv2.imshow('lena-not-juzicode',img_ret1)
 
img_ret2 = cv2.bitwise_not(img2)
print('img2[100,200]:    ',img2[100,200])
print('img_ret2[100,200]:',img_ret2[100,200])
cv2.imshow('logo-not-juzicode',img_ret2)
 
cv2.waitKey(0)
실행 결과:
cv2.__version__: 4.5.2
img1[161,199]:     [109 105 201]
img_ret1[161,199]: [146 150  54]
img2[100,200]:     [  0   0 255]
img_ret2[100,200]: [255 255   0]
예 를 들 어 lena.jpg 의 픽 셀 점[161,199]B 채널 의 값 은 109(0110 1101)이 고 반 된 값 은 146(1001 0010)이 며 바 이 너 리 로 전환 한 후에 모든 bit 가 0 이면 1 이 되 고 1 이면 0 이 되 는 것 을 관찰 했다.


위의 그림 에서 왼쪽 레 나 라 는 그림 은 마치 낯 익 은 듯 한 느낌 이 들 지 않 습 니까?뭔 지 기억 나 는 친구 가 나 이 를 드 러 낼 것 이다.20 년 전 유 행 했 던 필름 카메라,인화 한 필름 이 바로 이런 모습 이다.
반대로 OCR 문자 인식 을 할 때 일반적인 책 은 백지 흑자 이 고 배경 은 흰색 이기 때문에 식별 해 야 할 글 자 는 검은색 이다.이치 화 를 한 후에 식별 해 야 할 글 자 는 검은색 이다.만약 에 이미지 절단 을 직접 하면 목표 대상 인'흑자'가 아 닌 배경'백지'로 나 뉜 다.반대로 처리 하면 목표 의 흰색 문 자 를 자 르 는 효 과 를 얻 을 수 있다.다음 그림 은'백지 흑자'에서 앞 뒤의 대 비 를 취한 다.

bitwise_not()의 입 참 에는 1 개의 이미지 인 스 턴 스 만 입력 되 어 있 으 며,다음 에 소개 하 는 것 은 2 개의 이미지 인 스 턴 스(numpy 배열)또는 1 개의 이미지 인 스 턴 스 와 1 개의 스칼라 데이터 가 필요 합 니 다.그림 의 가감 곱 하기 연산 과 마찬가지 로 2 개의 그림 인 스 턴 스 와 관련 될 때 도 그림 의 행렬 수가 일치 하도록 요구 합 니 다.
2,위치 와 bitwiseand(),혹은 bitwiseor(),이 또는 bitwisexor()
비트 와,또는,이 또는 조작 에 따라 2 개의 이미지 대상 또는 1 개의 이미지 대상 과 1 개의 스칼라 데이터 가 상호작용 을 해 야 하 며 인터페이스 형식 은 다음 과 같다.
dst = cv2.bitwise_or(src1, src2[, dst[, mask]] )
dst = cv2.bitwise_or(src1, src2[, dst[, mask]] )
dst = cv2.bitwise_or(src1, src2[, dst[, mask]] )
다음은 두 그림 의 위치 와,또는,다른 예 입 니 다.

import cv2

print('cv2.__version__:',cv2.__version__)
 
img1 = cv2.imread('..\\lena.jpg' )[0:300,0:300]
img2 = cv2.imread('..\\messi5.jpg' )[0:300,0:300]
img_ret1 = cv2.bitwise_and(img1,img2)
print('img1[161,199]:    ',img1[161,199])
print('img2[161,199]:    ',img2[161,199])
print('img_ret1[161,199]:',img_ret1[161,199])
cv2.imshow('and-juzicode',img_ret1) 
 
img_ret2 = cv2.bitwise_or(img1,img2)
print('img_ret2[161,199]:',img_ret2[161,199])
cv2.imshow('or-juzicode',img_ret2) 
 
img_ret3 = cv2.bitwise_xor(img1,img2)
print('img_ret3[161,199]:',img_ret3[161,199])
cv2.imshow('xor-juzicode',img_ret3) 
 
cv2.waitKey(0)
실행 결과:
cv2.__version__: 4.5.2
img1[161,199]:     [109 105 201]
img2[161,199]:     [105  43  32]
img_ret1[161,199]: [105  41   0]
img_ret2[161,199]: [109 107 233]
img_ret3[161,199]: [  4  66 233]

두 그림 의 위치 별 조작 은 산술 연산 과 마찬가지 로 두 그림 의 크기 가 같 고 채널 수가 같 아야 한다.산술 연산 데이터 형식 과 다 를 때 dtype 을 통 해 새로 생 성 된 이미지 의 데이터 형식 을 설명 합 니 다.비트 연산 인터페이스 에 dtype 인자 가 전혀 없 기 때문에 비트 연산 에서 2 개의 이미지 의 데이터 형식 도 일치 해 야 합 니 다.
마찬가지 로 비트 연산 도 하나의 이미지 와 1 개의 스칼라 일 수 있 습 니 다.스칼라 데이터 형식 이 라면 1 개의 단독 수치 나 4 개의 수 치 를 포함 하 는 4 원 그룹 일 수 있 습 니 다.이 점 은 산술 연산 과 유사 합 니 다.산술 연산 과 달리 3 채널 의 그림 이 라면 3 개의 수 치 를 포함 한 3 원 그룹 과 이 그림 으로 스칼라 의 비트 연산 을 할 수 있다.
 아래 의 예 는 3 채널 이미지 와 4 원 그룹,3 원 그룹,단일 수치 로 비트 연산 을 하 는 예 입 니 다.

import cv2

print('cv2.__version__:',cv2.__version__)
 
img1 = cv2.imread('..\\lena.jpg' )[0:300,0:300]
img_ret1 = cv2.bitwise_and(img1,(0x3f,0x3f,0x3f,0))
print('img1[161,199]:    ',img1[161,199])
print('img_ret1[161,199]:',img_ret1[161,199])
cv2.imshow('and-juzicode',img_ret1) 
 
img_ret2 = cv2.bitwise_or(img1,(0x0f,0x0f,0x0f))
print('img_ret2[161,199]:',img_ret2[161,199])
cv2.imshow('or-juzicode',img_ret2) 
 
img_ret3 = cv2.bitwise_xor(img1,0xf0)
print('img_ret3[161,199]:',img_ret3[161,199])
cv2.imshow('xor-juzicode',img_ret3) 
 
cv2.waitKey(0)
실행 결과:
cv2.__version__: 4.5.2
img1[161,199]:     [109 105 201]
img_ret1[161,199]: [45 41  9]
img_ret2[161,199]: [111 111 207]
img_ret3[161,199]: [157 105 201]
그러나 그림 이 4 채널 을 포함 할 때 스칼라 데 이 터 를 처리 할 때 4 채널 을 0 으로 자동 으로 채 우지 않 기 때문에 4 채널 그림 을 처리 할 때 4 원 그룹 을 사용 해 야 합 니 다.좋 은 프로 그래 밍 습관 은 이미지 가 몇 채널 이 든 4 원 그룹 을 사용 하여 이 스칼라 를 표시 하 는 것 이다.만약 에 특정한 채널 에 대해 비트 연산 을 하지 않 으 려 면 해당 하 는 전 0 또는 전 f 로 대체 하 는 것 이다.예 를 들 어 3 채널 의 uint 8 유형의 이미 지 는 2 채널 과 0x 33 만 일치 해 야 한다.구조의 4 원 그룹 은(0xff,0x 33,0xff,0xff,0xff)이다.
3.부동 소수점 형식 이미지 의 비트 연산
앞의 예 에서 우 리 는 모두 uint 8 형식 을 예 로 들 어 설명 했다.물론 16 비트,32 비트 정형 데이터 형식의 이미지 처리 방법 은 유사 하지만 한 이미지 의 데이터 형식 이 부동 소수점 형식 이 라면 비트 연산 후의 결 과 는 어떻게 될 까?

import numpy as np
import cv2

print('cv2.__version__:',cv2.__version__)
 
img1 = np.array([0.7,0.8,0.9,1.0,1.1,1.2,1.3],dtype=np.float32).reshape(1,7)
img_ret1 = cv2.bitwise_not(img1)
print('img1:',img1)
print('img_ret1:',img_ret1)
실행 결과:
cv2.__version__: 4.5.2
img1: [[0.7 0.8 0.9 1.  1.1 1.2 1.3]]
img_ret1: [[-6.3999996 -5.5999994 -4.7999997 -3.9999998 -3.7999997 -3.5999997
  -3.3999999]]
위의 운행 결 과 를 보면 부동 소수점 은 위치 에 따라 반 전 된 데이터 와 원시 데이터 간 의 대 비 를 보면 기호 가 바 뀌 었 지만 이들 의 수 치 는 현저 한 대응 관계 가 없어 보인다.
이것 은 부동 소수점 데이터 가 메모리 에 저장 되 는 방식 에 의 해 결정 되 며,단일 정밀도 32 비트 부동 소수점 은 1 개의 기호 비트 S+8 개의 지수 비트 E+23 개의 유효 수치 비트 M 으로 구성 된다.0.7 의 경우 Python 에서 float.hex(0.7)로 계산 한 결 과 는 0x 1.66666666666666666666p-1 로 23 개의 유효 수치 비트 M=0110 0110 0110 0110 0110 011,지수 E=127-1=0x7E=0b 0111 1110,기호 비트 S=0 을 취하 기 때문에 완전한 수 치 는 0b 0 이다. 0111 1110 0110 0110 0110 0110 011=0x3f 33333,반대로 취하 면 0xc0cccccc 이 고,다시 반대로 부동 소수점 의 값 을 계산 하면-6.3999996 이 며,같은 방법 으로 다른 부동 소수점 2 진법 표시 방법 을 계산 할 수 있다.
Python 에서 부동 소수점 의 바 이 너 리 수 치 를 직접 인쇄 하여 표시 하 는 방법 이 없 기 때문에,우 리 는 C 언어 에서 포인터 형식 을 강제로 변환 하 는 방식 으로 부동 소수점 의 바 이 너 리 값 을 관찰 하고 변환 할 수 있 습 니 다.다음 예 에서 우 리 는 먼저 float 형의 배열 을 정의 한 다음 에 순환 에서 배열 의 모든 요 소 를 순서대로 처리 합 니 다.먼저 이 수 치 를(int*)강제 형식 으로 전환 한 다음 에 이 int 형식의 데 이 터 를 반 조작 한 다음 에 반 수 된 int 형식 을 강제로 float 형 으로 전환 합 니 다.

#include "stdio.h"
int main(void)
{
    float arr_f[7] = { 0.7,0.8,0.9,1.0,1.1,1.2,1.3 }; //       
    int arr_i[7];               //         int 
    int arr_i_not[7];           //  int      
    float arr_f_not[7];         //arr_i_not      
    for (int i = 0; i < 7; i++) {
        int *t_i = (int*)(arr_f + i); //       int 
        arr_i[i] = *t_i;
        arr_i_not[i] = ~arr_i[i];
        float *t_f = (float*)(arr_i_not + i);
        arr_f_not[i] = *t_f;
    }
 
    for (int i = 0; i < 7;i++) {
        printf("%0.7f  ", arr_f[i]); 
        printf("%x  ", arr_i[i]);
        printf("%x  ", arr_i_not[i]);
        printf("%0.7f  
", arr_f_not[i]); } return 0; }
실행 결 과 는 다음 과 같 습 니 다.첫 번 째 열 은 원시 데이터 이 고 마지막 열 은 위치 에 따라 반 전 된 수 치 를 취하 고 OpenCV 의 bitwise 입 니 다.not()계산 결과 가 같 습 니 다.
0.7000000  3f333333  c0cccccc  -6.3999996
0.8000000  3f4ccccd  c0b33332  -5.5999994
0.9000000  3f666666  c0999999  -4.7999997
1.0000000  3f800000  c07fffff  -3.9999998
1.1000000  3f8ccccd  c0733332  -3.7999997
1.2000000  3f99999a  c0666665  -3.5999997
1.3000000  3fa66666  c0599999  -3.3999999
OpenCV 내부 에서 부동 소수점 유형 에 대한 비트 연산 도 실제 적 으로 이 진 수치 에 따라 전환 되 지만 이런 전환 방법 은 매우 명확 한 이미지 학 적 의미 가 없 기 때문에 일반 부동 소수점 유형의 비트 연산 은 거의 사용 되 지 않 는 다.
여기 서 OpenCV-Python 튜 토리 얼 이미지 의 비트 연산 에 대한 상세 한 설명 을 소개 합 니 다.더 많은 OpenCV-Python 이미지 와 관련 된 비트 연산 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 지원 바 랍 니 다!

좋은 웹페이지 즐겨찾기