2017년 8월 15일 화요일

opencv histogram equalize, CDF graph 출력


















1. histogram (PDF) 구하고
2. CDF 구하고
3. Y(imageout) = CDF(imagein)


#pragma warning(disable: 4819)

#include "opencv2/opencv.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(void)
{
    Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);if (src.empty()) {      cerr << "Image load failed!" << endl;       return -1;  }
    
    int hist[256] = { 0, };
    for (int j = 0; j < src.rows; j++) {
        for (int i = 0; i < src.cols; i++) {
            hist[src.at<uchar>(j,i)]++;
        }
    }
    int hist_max = 0;
    for (int i = 0; i < 256; i++) {
        if (hist[i] > hist_max)
            hist_max = hist[i];
    }
    Mat histogram_original;
    histogram_original.create(256,256, CV_8U);
    histogram_original.setTo(0);
    int N=0;
    for (int i = 0; i < 256; i++) {
        int v = (double) (255.* hist[i])/ hist_max;
        v = cvRound(v);
        for (int j = 0; j < v; j++) {
            histogram_original.at<uchar>(255-j, i) = 255;
        }
    }
    int CDF[256] = { 0, };
    CDF[0] = 0;
    for (int i = 1; i < 256; i++) {
        CDF[i] = hist[i] + CDF[i - 1];
    }
    //CDF normalize
    for (int i = 1; i < 256; i++) {
        CDF[i] = cvRound(255.*CDF[i]/CDF[255]);
    //  CDF[i] = 255.*CDF[i] / CDF[255];
    }
    Mat CDFdrawing;
    CDFdrawing.create(256, 256, CV_8U);
    CDFdrawing.setTo(255);
    for (int i = 0 ; i < 256; i++) {
        line(CDFdrawing, Point(i, 255 - CDF[i]), Point(i, 255 - CDF[i]), 0);
    }
    //imshow("dst", dst);
    //CDF function Y(output) = CDF(input)

    Mat src2 = src.clone();
    Mat dst(src2.rows, src2.cols, src2.type());
    for (int i = 0; i < src2.rows; i++) {
        for (int j = 0; j < src2.cols; j++) {
            dst.at<uchar>(j, i) = CDF[(uchar)src2.at<uchar>(j, i)];
        }
    }
    imshow("src", src);
    imshow("histogram_original", histogram_original);
    imshow("CDFdrawing", CDFdrawing);
    imshow("dst", dst);


    //check equalized Image historam, CDF
    
    int hist2[256] = { 0, };
    for (int j = 0; j < dst.rows; j++) {
        for (int i = 0; i < dst.cols; i++) {
            hist2[dst.at<uchar>(j, i)]++;
        }
    }
    int hist2_max = 0;
    for (int i = 0; i < 256; i++) {
        if (hist2[i] > hist2_max)
            hist2_max = hist2[i];
    }
    Mat histogram_equalized;
    histogram_equalized.create(256, 256, CV_8U);
    histogram_equalized.setTo(0);
    int N2 = 0;
    for (int i = 0; i < 256; i++) {
        int v = (double)(255.* hist2[i]) / hist2_max;
        v = cvRound(v);
        for (int j = 0; j < v; j++) {
            histogram_equalized.at<uchar>(255 - j, i) = 255;
        }
    }
    int CDF2[256] = { 0, };
    CDF2[0] = 0;
    for (int i = 1; i < 256; i++) {
        CDF2[i] = hist2[i] + CDF2[i - 1];
    }
    //CDF normalize
    for (int i = 1; i < 256; i++) {
        CDF2[i] = cvRound(255.*CDF2[i] / CDF2[255]);
        //  CDF[i] = 255.*CDF[i] / CDF[255];
    }
    Mat CDFdrawing2;
    CDFdrawing2.create(256, 256, CV_8U);
    CDFdrawing2.setTo(255);
    for (int i = 0; i < 256; i++) {
        line(CDFdrawing2, Point(i, 255 - CDF2[i]), Point(i, 255 - CDF2[i]), 0);
    }
    imshow("histogram_equalized", histogram_equalized);
    imshow("CDF_equalized", CDFdrawing2);
    waitKey(0);
    return 0;
}

2017년 8월 13일 일요일

opencv createTrackbar 응용_1 X축 휘도분포 보기

3,4 모르겠음..아시면 누가 답변좀

1.src.copyTo(dst)
2.profile.setTo(255)  //Mat profile;
3. uchar* pSrc   *pSrc는 포인터 변수이고 주소가 나타내는 값을 uchar로 저장한다는 의미?
4.src.ptr이 포인터형 주소값을 나타내는 상황에서 이 포인터가 나타내는 값을 uchar로 받겠다는 의미? (uchar*)src.ptr
->명시적 형변환

5. <uchar>(row)< row값을 uchar 형으로 형변환하여 받는다는 의미?

->Mat 자료형에서 ptr이 const로 되어있는 상황에서  <>(const_cast) 를 해줌으로써 상수형을 비상수형으로 바꾼다음 넣어줄수 있다.
실제로 (uchar)(row)하면 error 발생











5번 참고자료
-------------------------------------------------------
const_cast

const_cast 는 상수 포인터에서 const (변수의 상수화) 속성이나 volatile(변수에 대해 컴파일러가 최적화를 못하게 만드는것) 속성을 제거

할때 사용하며 , 상수포인터로 선언된것을 비상수 포인터에 값을 넣을때 사용된다. 일반적으로는 비상수 포인터에 상수형 포인터를 넣지

못하지만 const cast 를 사용해서 상수형을 비상수형으로 바꾼다음 값을 넣어줄수 있는 것이다.
  
const_cast<자료형 *>(대상 변수명);



[출처] [C/C++] 형변환|작성자 늑대발바닥

-------------------------------------------------------



    src.copyTo(dst);
    profile.setTo(255);
    uchar value;
    uchar* pSrc = (uchar*)src.ptr<uchar>(row);
    uchar* pDst = (uchar*)dst.ptr<uchar>(row);

6.  그래프 좀더 정확하게 표현하려면
시작점 끝점 동일하게 하면 되지만 보기가 힘들다.

    for (int i = 1; i < src.cols; i++) {
        line(profile, Point(i - 1, 255 - pSrc[i - 1]), Point(i - 1, 255 - pSrc[i-1]), 0);
        pDst[i] = saturate_cast<uchar>(pSrc[i] + 50);
    }

practice_3_profile

#pragma warning(disable: 4819)

#include "opencv2/opencv.hpp"
#include <iostream>

using namespace cv;
using namespace std;
void on_trackbar(int, void*);
Mat src, dst, profile;
int row = 0;    
int main(void)
{
    src = imread("lenna.bmp", IMREAD_GRAYSCALE);    if (src.empty()) {      cerr << "Image load failed!" << endl;       return -1;  }
    profile.create(256, src.cols, CV_8U);
    namedWindow("dst");
    namedWindow("profile");
    createTrackbar("Profile", "dst", &row, src.rows - 1, on_trackbar, NULL);
    on_trackbar(0, 0);
    waitKey(0);
    return 0;
}
void on_trackbar(int, void*)
{
    src.copyTo(dst);
    profile.setTo(255);
    uchar value;
    uchar* pSrc = (uchar*)src.ptr<uchar>(row);
    uchar* pDst = (uchar*)dst.ptr<uchar>(row);
    for (int i = 1; i < src.cols; i++) {
        line(profile, Point(i - 1, 255 - pSrc[i - 1]), Point(i, 255 - pSrc[i]), 0);
        pDst[i] = saturate_cast<uchar>(pSrc[i] + 50);
    }
    imshow("dst", dst);
    imshow("profile", profile);
}

2017년 8월 12일 토요일

opencv 영상의 평균밝기를 지나는 직선의 방정식의 기울기를 trackbar 로 조절


1.전역변수 선언 필요
 - 반환할 주소 값 나타내는 변수 여기선 alpha
 - main, 외부함수에서 사용할 Mat 형 변수.
 - 전역변수 선언 안하고 void* userdata=0; 구문 바꾸어서 데이터 전달하려고 시도했으나
   실패..

2.createTrackbar("트랙바이름", "표시될위치",int 값 반환할 주소, 트랙바에서 최대값, 슬라이더 위치 바뀌면 실행 될 콜백 함수,?)

    namedWindow("controled");
    createTrackbar("brigtnesscontrol", "controled", &alpha, 256*8/* alpha max 8로 설정*/, on_trackbar, NULL); 


3.콜백함수
콜백함수 모르겠음..
void on_trackbar(int, void*);


4.code

adjcont

#pragma warning(disable: 4819)

#include "opencv2/opencv.hpp"
#include <iostream>

using namespace cv;
using namespace std;

void on_trackbar(int, void*);
Mat dst,src;
int alpha=4*256;//alpha 값 최대 256*8
double input_image_luminous_sum = 0;
double output_image_luminous_sum = 0;
int pixel_count;
int input_img_lumi_mean = 0;

int main(int argc, char** argv)
{
    src = imread("lenna.bmp", IMREAD_GRAYSCALE);    if (src.empty()) { cerr << "Image load failed!" << endl; return -1; }
    dst.create(src.rows, src.cols, src.type());
    pixel_count = (src.rows)*(src.cols);
    // 평균 휘도 구하기
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            input_image_luminous_sum = src.at<uchar>(i, j) + input_image_luminous_sum;
        }
    }
    input_img_lumi_mean = input_image_luminous_sum / pixel_count; // 평균 휘도
    namedWindow("controled");
    createTrackbar("brigtnesscontrol", "controled", &alpha, 256*8/* alpha max 8로 설정*/, on_trackbar, NULL);
    
    cout << "input image 평균휘도 (input_image_luminous_mean/pixel_count) : " << input_image_luminous_sum / pixel_count << "\n" << endl;
    cout << "초기 alpha : " << alpha/256. << "\n" << endl;
    imshow("src", src);
    dst = src + (src - input_img_lumi_mean)*(alpha / 256.);
    imshow("dst", dst);
    waitKey(0);
    return 0;
}

void on_trackbar(int, void*) {
    output_image_luminous_sum = 0;
    dst = src + (src - input_img_lumi_mean)*(alpha / 256.);
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            output_image_luminous_sum = dst.at<uchar>(i, j) + output_image_luminous_sum;
        }
    }
    cout << "output image 평균휘도 (output_image_luminous_mean/pixel_count) : " << (output_image_luminous_sum / pixel_count) << "\n" << endl;
    cout << "alpha : " << alpha/256. << "\n" << endl;
    imshow("src", src);
    imshow("dst", dst);
}

2017년 8월 5일 토요일

<Visual C++의 유용한 단축키> : Help->Keyboard Map 참고
줄넘버 보여주기 :
도구 > 옵션 > 텍스트편집기 > 모든언어 > 자동줄번호 선택.

<이동>-------------------------------------------------
Ctrl + F2               현재 라인에 북마크 지정/해제
F2                       지정된 다음 북마크로 이동
Ctrl + Shift + F2      지정된 모든 북마크를 해제
Ctrl-K, Ctrl-H         바로가기 설정. ( 작업목록 창에서 확인가능 )
Ctrl-K,K                북마크 설정 / 해제
Ctrl-K,L                북마크 모두 해제
Ctrl-K,N                북마크 다음으로 이동
Ctrl-K,P                북마크 이전으로 이동
Ctrl-K,C                선택한 블럭을 전부 코멘트
Ctrl-K,U                선택한 블럭을 전부 언코멘트(코멘트 해제)
Ctrl + ] 또는 E        {괄호의 짝을 찾아줌
Ctrl + J, K              #ifdef  #endif의 짝을 찾아줌
Ctrl+ -, Ctrl+Shift+ -
현재 커서를 기억하는 Ctrl+F3(VS6에서), Ctrl+K,K(VS7에서와는 달리 사용자가 별도로 입력을 해주는건 없고단지 이전에 커서가 있었던곳으로 위 키를 누를 때마다 이동된다. (shift를 이용하면 역순)

Ctrl-F12                커서위치 내용의 선언(.h)으로 이동
F12                      커서위치 내용의 정의(.cpp)로 이동
Shift+Alt+F12         빠른기호찾기

Ctrl-Shift-G           #include "파일명파일로 바로 직접이동
F8                       After a build failure hit
Shift+F8            거꾸로
Ctrl + D                툴바의 찾기 Editbox로 이동 

<편집>-------------------------------------------------
Ctrl-F                   찾기 대화상자
Ctrl-H                  바꾸기 대화상자
Ctrl-Shift-F           파일들에서 찾기 대화상자
Ctrl-Shift-H           파일들에서 바꾸기 대화상자
Ctrl-G                  해당 줄로 가기 (별로 필요없음)
Ctrl-K,Ctrl-F          선택된 영역 자동 인덴트 (VS6 Alt-F8기능)
Ctrl-Shift-Spacebar             함수와매개변수설명이 안나올경우강제로 나오게
Ctrl+Alt+T
Ctrl+Spacebar       멤버목록 팝업창이 나타납니다
Ctrl+Shift+R           (키보드 레코딩)
             가끔 연속된 연속기만으로는 부족한경우가 있다.
             이때 Ctrl+Shift+R 을 누르고원하는 동작들을 수행후,
다시 Ctrl+Shift+R을 눌러 종료한다. 
이 중간동작을 원하는 위치에서 반복하고 싶다면
             Ctrl+Shift+P 를 누른다.

Ctrl+Shift+V           (히스토리 붙이기)
Ctrl-Z                  이전으로 되돌리기
Ctrl-Shift-Z           되돌렸다다시 복구하기
Ctrl + I                  문자열 입력점진적으로 문자열 찾기
Ctrl + F3               현재 커서에 있는 문자열 찾기
Ctrl+Shift+F3          거꾸로 찾기
F3                       찾은 문자열에 대한 다음 문자열 (Next Search)
Ctrl + H                 문자열 찾아 바꾸기 (Replace)
Ctrl + Left/Right     단어 단위로 이동
Ctrl+[Delete|Backspace] 단어 단위로 삭제
Ctrl + L                 한 라인을 클립보드로 잘라내기
Ctrl + Shift + L       한 라인을 삭제
Alt + Mouse          세로로 블록 설정하기 (마우스로)
Ctrl + Shift + F8      세로로 블록 설정하기 (키보드로),
취소할 때는 Esc키를 눌러야 함
블록설정>>Tab       선택된 블록의 문자열을 일괄적으로 들여쓰기(Tab)
블록설정>>Shift + Tab선택된 블록의 문자열을 일괄적으로 내어쓰기
Alt+F8>> [Tab|Shift + Tab]
                          들여쓰기 자동 조정
Ctrl + T                 현재 커서에 있는 변수/함수에 대한 Type
Tooltip 힌트 창에 나타남
Ctrl + Alt + T          멤버 변수/함수 목록에 대한 팝업 창이 나타남
Ctrl + Shift + T       공백/콤마/파이프/괄호 등을 기준으로
좌우 문자열을 Swap시킴
Ctrl + Shift + 8       문단기호 표시/감추기 :
Tab ^, Space .으로 표시
Ctrl + D                 툴바의 찾기 Editbox로 이동
Ctrl + Up/Down      커서는 고정시키고 화면만 스크롤 시키기
CTRL+SHIFT+T       커서 위치의 단어와 앞 단어가 서로 교체
ALT+SHIFT+T         커서 위치의 한줄과 윗줄이 서로 교환
Ctrl + Shift + U       소문자가 대문자로 둔갑.
Ctrl + U                 대문자를 소문자로 변경
Ctrl + Shift + F8      블럭설정
Ctrl + C, C                          That copies the current line.
Ctrl+K, Ctrl+C                      Automatically commented.
Ctrl+K, Ctrl+U                      Uncommented.

<디버그/빌드>-------------------------------------------
F5                       디버그 시작
F9                       디버그 브렉포인트 지정/해제
Ctrl-F9                 현위치 설정된 브렉포인트 해제
Ctrl-Shift-F9         현재 소스파일에 지정된 모든 Breakpoint 해제
Shift-F5               디버그 빠져나오기
Ctrl-F10                커서가 있는곳까지 실행
Shift-F11                           현 함수를 빠져나감.

Shift+Ctrl+B           전체 빌드(프로젝트가 여러개있을경우 모두 빌드)
Alt+B, C                해당 프로젝트만 정리.
Alt+B, U                해당 프로젝트만 빌드.
Ctrl-F7                 현 파일만 컴파일    현 프로젝트만 빌드
Ctrl-F5                 프로그램 시작
Shift + F9                           디버그 모드에서 추가하고픈 변수나 등등
앞에 커서를 위치 시킨후 Shift+F9를 누르면
Watch Window에 자동으로 추가.

<창관련>-----------------------------------------------
Shift+Alt+Enter       전체 창 (토글 됨)
F4                       속성창 보여준다.
Ctrl+Alt+X                           리소스에디터 툴박스창
Ctrl+Alt+K              작업목록 창.
Ctrl + Tab                           Edit하고 있는 Child Window 간의 이동
Ctrl + F4               현재 Edit하고 있는 Child Window를 닫기
Ctrl-M, Ctrl-L         소스파일의 함수헤더만 보이기 (구현부는 감추고)
Ctrl-M, Ctrl-M        현재 커서가 위치한 함수를 접는다/편다. (토글 키)
Ctrl+R, Ctrl+R         Word Wrap
Ctrl+M+L               편집.전체개요표시숨기기

Ctrl+M+H           편집.선택영역숨기기
Ctrl+M+U           편집.현재숨기기중지

Alt + F7                Project Setting




opencv 픽셀 접근방법 시간 비교(픽셀 포인터 : at VS 행 단위 포인터 접근 : ptr)

픽셀 포인터 : at
행 단위 포인터 접근 : ptr 차이를 알아보기 위해 입력이미지에 상관없이 평균 밝기를 128로 만들어 주는 코드로 속도차이를 비교해 보았다.

lenne.bmp(512*512, gray color) 파일로 실험해보면
행단위 포인터 접근 방법이 더 빠르다.

release mode


debug mode : 시간 측정시 전혀 고려대상이 아님...


#include "opencv2/core/ocl.hpp"
main 문 안에 추가
cv::ocl::setUseOpenCL(false);

#pragma warning(disable: 4819)

#include "opencv2/opencv.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(void)
{
    int pixel_count = 0;
    double image_luminous_sum = 0;
    double output_image_luminous_sum = 0;
    int64 t1, t2, t3,t4,t5,t6;
    Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
    if (src.empty()) {
        cerr << "Image load failed!" << endl;
        return -1;
    }
    pixel_count = (src.rows)*(src.cols);
    cout << "input image pixel : " << pixel_count << "\n" << endl;
    /////////////////////////////////////////////////////////////////////////////
    
    t1 = getTickCount();
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            image_luminous_sum = src.at<uchar>(i, j) + image_luminous_sum;
        }
    }
    Mat dst = src*128*pixel_count/image_luminous_sum;
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            output_image_luminous_sum = dst.at<uchar>(i, j)+ output_image_luminous_sum;
        }
    }
    t3 = getTickCount();
    double ms1 = (t3 - t1) * 1000 / getTickFrequency();

    cout << "image_luminous_sum : " << image_luminous_sum << "\n" << endl;
    cout << "image_luminous_mean : " << (output_image_luminous_sum / pixel_count) << "\n" << endl;
    cout << "픽셀 포인터 연산 시간 : " << ms1 <<" ms "<<"\n" << endl;
    
    /////////////////////////////////////////////
    
    image_luminous_sum = 0;
    output_image_luminous_sum = 0;
    t4 = getTickCount();
    for (int i = 0; i < src.rows; i++) {
        uchar* p = src.ptr<uchar>(i);
        for (int j = 0; j < src.cols; j++) {
            image_luminous_sum = p[j] + image_luminous_sum;
        }
    }
    Mat dst2 = src * 128 * pixel_count / image_luminous_sum;
    for (int i = 0; i < src.rows; i++) {
        uchar* p2 = dst2.ptr<uchar>(i);
        for (int j = 0; j < src.cols; j++) {
            output_image_luminous_sum = p2[j] + output_image_luminous_sum;
        }
    }
    t6 = getTickCount();
    double ms4 = (t6 - t4) * 1000 / getTickFrequency();
    cout << "image_luminous_sum : " << image_luminous_sum << "\n" << endl;
    cout << "image_luminous_mean : " << (output_image_luminous_sum / pixel_count) << "\n" << endl;
    cout << "행 단위 포인터 접근방법 연산 시간: " << ms4 << " ms "<< "\n" << endl;
    imshow("src", src);
    imshow("dst", dst);
    imshow("dst2", dst2);
    waitKey(0);
    return 0;
}