Round A APAC Test 2017

本文分享了作者参加CodeJam比赛的经历与遗憾,并详细解析了四个赛题:CountryLeader、Rain、Jane's Flower Shop及Clash Royale的题意与解题思路。

题目链接:https://code.google.com/codejam/contest/11274486/dashboard

结果真是遗憾,排名比200多一点点。败在了对规则的不了解上,当然实力还是渣。唉毕竟第一次比赛,才发现居然tmd和练习赛是不一样的。分数最高的第四题大数据,我下载下来开始运行然后喝了个水去了个厕所,回来就显示超时了,最重要的是发现不能再次下载(小数据就算incorrect还是可以重新下载数据然后运行提交的)。一开始我以为是它平台的bug,于是无限次刷新,换浏览器,重启电脑,发现还是这样。时间就这样耗过去了,比赛结束才知道大数据就一次提交机会,切记切记!最伤心的是我的程序是对的。唉,就当交学费了吧。

记录一下吧:

Problem A. Country Leader

The Constitution of a certain country states that the leader is the person with the name containing the greatest number of different alphabet letters. (The country uses the uppercase English alphabet from A through Z.) For example, the name GOOGLE has four different alphabet letters: E, G, L, and O. The name APAC CODE JAM has eight different letters. If the country only consists of these 2 persons, APAC CODE JAM would be the leader.

If there is a tie, the person whose name comes earliest in alphabetical order is the leader.

Given a list of names of the citizens of the country, can you determine who the leader is?
Input

The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with a line with an interger N, the number of people in the country. Then N lines follow. The i-th line represents the name of the i-th person. Each name contains at most 20 characters and contains at least one alphabet letter.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the name of the leader.
Limits

1 ≤ T ≤ 100.
1 ≤ N ≤ 100.
Small dataset:Each name consists of at most 20 characters and only consists of the uppercase English letters A through Z.

Large dataset:Each name consists of at most 20 characters and only consists of the uppercase English letters A through Z and ' '(space).
All names start and end with alphabet letters.

题意:给定若干个只含有大写字母和空格的字符串,按照特定的规则选出最牛逼的。规则是先比较出现的字母数量,如果相同,则按照字典序排序。

思路:直接模拟呗,大小数据N都是小于100,所以直接排序也没什么问题。

#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
using namespace std;
int T,n,m;
struct node{
    char s[25];
    int t;
}s[105];
int flag[258];
int cmp(node a,node b){
    if(a.t == b.t)
        return strcmp(a.s, b.s)<0;
    return a.t>b.t;
}
int main(){
    scanf("%d",&T);
    for(int z = 1;z<=T;z++){
        scanf("%d\n",&n);
        for(int i = 0;i<n;i++){
            gets(s[i].s);
            memset(flag, 0, sizeof(flag));
            for(int j = 0;s[i].s[j];j++)
                if(s[i].s[j] !=' ')
                    flag[s[i].s[j]-'A'] = 1;
            s[i].t = 0;
            for(int j = 0;j<26;j++)
                if(flag[j])
                    s[i].t++;
        }
        sort(s,s+n,cmp);
        printf("Case #%d: %s\n",z,s[0].s);
    }
    return 0;
}

Problem B. Rain

There's an island in the sea. The island can be described as a matrix with R rows and C columns, with H[i][j] indicating the height of each unit cell. Following is an example of a 3*3 island:
3 5 5
5 4 5
5 5 5
Sometimes, a heavy rain falls evenly on every cell of this island. You can assume that an arbitrarily large amount of water falls. After such a heavy rain, some areas of the island (formed of one or more unit cells joined along edges) might collect water. This can only happen if, wherever a cell in that area shares an edge (not just a corner) with a cell outside of that area, the cell outside of that area has a larger height. (The surrounding sea counts as an infinite grid of cells with height 0.) Otherwise, water will always flow away into one or more of the neighboring areas (for our purposes, it doesn't matter which) and eventually out to sea. You may assume that the height of the sea never changes. We will use W[i][j] to denote the heights of the island's cells after a heavy rain. Here are the heights of the example island after a heavy rain. The cell with initial height 4 only borders cells with higher initial heights, so water will collect in it, raising its height to 5. After that, there are no more areas surrounded by higher cells, so no more water will collect. Again, note that water cannot flow directly between cells that intersect only at their corners; water must flow along shared edges.
Following is the height of the example island after rain:
3 5 5
5 5 5
5 5 5
Given the matrix of the island, can you calculate the total increased height sum(W[i][j]-H[i][j]) after a heavy rain?
Input

The first line of the input gives the number of test cases, T. T test cases follow.
The first line of each test case contains two numbers R and C indicating the number of rows and columns of cells on the island. Then, there are R lines of C positive integers each. The j-th value on the i-th of these lines gives H[i][j]: the height of the cell in the i-th row and the j-th column.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the total increased height.

Limits

1 ≤ T ≤ 100.
1 ≤ H[i][j] ≤ 1000.
Small dataset

1 ≤ R ≤ 10.
1 ≤ C ≤ 10.
Large dataset

1 ≤ R ≤ 50.
1 ≤ C ≤ 50.

题意:一个n*m矩形区域,其中每个1*1都是有高度的矩形块,高低起伏,求最多储水量。(边界不能储水)

思路:先将边界装入优先队列中(高度越小越优先),并标记为已访问。看队首元素四周未访问过的点,1、如果该点不比队首低,则将它加入队列,标记为已访问,即它变成了新的边界。2、该点比队首低,意味着该点可以储水,更新res值,同时将它加入队列中,但是它的高度为原队首元素的高度,即以它为边界的点不能超过这个高度,同时将该点标记为已访问。

#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
using namespace std;
#define N 55
int s[N][N],used[N][N],res;
int T,n,m;
struct node{
    int x,y,h;
    node(int xx,int yy,int hh):x(xx),y(yy),h(hh){};
    bool operator<(const node b)const{
        return h>b.h;
    }
};
int ori[4][2] = {{0,-1},{0,1},{-1,0},{1,0}};
int check(int x,int y){
    return x>=0&&x<n&&y>=0&&y<m&&(!used[x][y]);
}
int main(){
    scanf("%d",&T);
    for(int z = 1;z<=T;z++){
        res = 0;
        memset(used, 0, sizeof(used));
        priority_queue<node> q;
        scanf("%d %d",&n,&m);
        for(int i = 0;i<n;i++)
            for(int j = 0;j<m;j++){
                scanf("%d",&s[i][j]);
                if(i==0||i==n-1||j==0||j==m-1){
                    q.push(node(i,j,s[i][j]));
                    used[i][j] = 1;
                }
            }
        while(!q.empty()){
            node now = q.top();
            q.pop();
            for(int i = 0;i<4;i++){
                int xx = now.x+ori[i][0];
                int yy = now.y+ori[i][1];
                if(check(xx, yy)){
                    if(s[xx][yy] >= now.h)
                        q.push(node(xx,yy,s[xx][yy]));
                    else{
                        res += now.h-s[xx][yy];
                        q.push(node(xx,yy,now.h));
                    }
                    used[xx][yy] = 1;
                }
            }  
        }  
        printf("Case #%d: %d\n",z,res);
    }
    return 0;
}

Problem C. Jane's Flower Shop

Jane plans to open a flower shop in the local flower market. The initial cost includes the booth license, furnishings and decorations, a truck to transport flowers from the greenhouse to the shop, and so on. Jane will have to recoup these costs by earning income. She has estimated how much net income she will earn in each of the following M months.

Jane wants to predict how successful her flower shop will be by calculating the IRR (Internal Rate of Return) for the M-month period. Given a series of (time, cash flow) pairs (i, Ci), the IRR is the compound interest rate that would make total cash exactly 0 at the end of the last month. The higher the IRR is, the more successful the business is. If the IRR is lower than the inflation rate, it would be wise not to start the business in the first place.

For example, suppose the initial cost is $10,000 and the shop runs for 3 months, with net incomes of $3,000, $4,000, and $5,000, respectively. Then the IRR r is given by:

-10000*(r+1)^3 + 3000*(r+1)^2 + 4000*(r+1) + 5000 = 0

In this case, there is only one rate (~=8.8963%) that satisfies the equation.

Help Jane to calculate the IRR for her business. It is guaranteed that -1 < r < 1, and there is exactly one solution in each test case.

Input

The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with a positive integer M: the number of months that the flower shop will be open. The next line contains M + 1 non-negative integers Ci (0 ≤ i ≤ M). Note that C0 represents the initial cost, all the remaining Cis are profits, the shop will always either make a positive net profit or zero net profit in each month, and will never have negative profits.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is a floating-point number: the IRR of Jane's business. y will be considered correct if it is within an absolute or relative error of 10-9 of the correct answer. See the FAQ for an explanation of what that means, and what formats of real numbers we accept.

Limits

1 ≤ T ≤ 100.
C0 > 0.
0 ≤ Ci ≤ 1,000,000,000.
Small dataset

1 ≤ M ≤ 2.
Large dataset

1 ≤ M ≤ 100.

题意:题意很简单,就是给一个方程,题目保证解唯一,求这个解。

思路:这道题真是觉得自己没用,其实很简单。一开始没细想直接写了个二分,写到一半发现没考虑单调性,然后求了个导发现没用。然后就手足无措中,以为要用模拟退火等等高科技了。怕耽误太久就先把小数据过了(这个小数据的范围明摆了就是解方程,一次方程和二次方程,好在公式还没忘)。比赛结束自己又想了一下,顿时捶胸顿足,显然r=-1的时候方程值大于0,而解又保证唯一,那么在r∈[-1,1]之间,必然零点左边都是大于0,右边都是小于0的。所以就是二分,擦。。。

#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
#define N 105
int s[N];
int T,n,m;
int test(double &x){
    double sum = -s[0]*pow((1+x),n);
    for(int i = 1;i<=n;i++)
        sum += s[i] * pow((1+x),n-i);
    if(sum > 1e-15)
        return 1;
    if(sum < -1e-15)
        return -1;
    return 0;
}
int main(){
    scanf("%d",&T);
    for(int z = 1;z<=T;z++){
        scanf("%d",&n);
        for(int i = 0;i<=n;i++)
            scanf("%d",&s[i]);
        double low = -1.,high = 1.,mid;
        while(high-low >= 1e-15){
            mid = (low+high) / 2;
            int j = test(mid);
            if(j<0)
                high = mid;
            else if(j>0)
                low = mid;
            else
                break;
        }
        printf("Case #%d: %.12lf\n",z,mid);
    }
    return 0;
}



Problem D. Clash Royale

Clash Royale is a real time strategy card game. Each card has an attack power and a level. Each player picks 8 cards to form a battle deck; the total attack power of a deck is the sum of the attack power of each of its cards. Players fight with each other by placing cards from their battle decks into the battle arena. The winner of a battle is rewarded with coins, which can be used to upgrade cards. Upgrading a card increases its attack power. <p/>

After days of arena fighting, Little Shawn has accumulated a total of M coins. He has decided to upgrade some of his cards. Little Shawn has N cards. The i-th card can have any level from 1 through Ki; the attack power for the j-th level is Ai,j. Cards must be upgraded one level at a time; the price to upgrade the i-th card from level j to level j+1 costs Ci,j coins. The i-th card is currently at level Li before Little Shawn has upgraded any cards.

Little Shawn wants to use some or all of his coins to upgrade cards, and then form a deck of exactly 8 cards, so that the deck's total attack power is as large as possible. Can you help him do this? He can upgrade the same card more than once as long as he can afford it, and he does not have to upgrade every card.

Input

The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with 2 integers M and N, the number of coins and the number of cards that Little Shawn possesses. Then N blocks follow. The i-th block consists of 3 lines describing the i-th card. The first line contains two integers Ki and Li, the maximum possible level and current level of the card. The second line contains Ki integers Ai,1, Ai,2, ..., Ai,Ki, the attack power of each level. The third line contains Ki-1 integers Ci,1, Ci,2, ..., Ci,Ki-1, the number of coins required to upgrade a card that is currently at level 1, 2, ..., Ki-1.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the maximal possible total attack power of a deck that Little Shawn can form, using the coins that he has.

Limits

1 ≤ T ≤ 100.
1 ≤ Ki ≤ 10.
1 ≤ Li ≤ Ki.
Ai,j < Ai,j+1.
Small dataset

1 ≤ M ≤ 1,000.
N = 8.
1 ≤ Ai,j ≤ 1,000.
1 ≤ Ci,j ≤ 1,000.
Large dataset

1 ≤ M ≤ 1,000,000,000.
8 ≤ N ≤ 12.
1 ≤ Ai,j ≤ 1,000,000,000.
1 ≤ Ci,j ≤ 1,000,000,000.

题意:一个人有8~12张卡片,每张卡片有其特有的最大的级别,高的级别带来更高的收益,然后升级是需要钱的,升级只能一级一级升,而且从i级升到i+1级别需要的钱都是不同的。现在给定一定的钱数,问最后选出8个卡片,能够达到的最大的收益之和。

思路:反正我的做法在大数据上5s之内跑完,还没仔细想有没有别的做法。思路就是先从12个卡片枚举选出8个来,对于选出来的8个,直接暴搜。复杂度是C12,8 * 10^8。当然里面有两个剪枝:一个是钱数不够了直接退出,另外一个是先预先算出所有卡片升级到最高需要的钱数,暴搜的过程中看看如果后面的都升到最高级也没有最优值好就退出。

#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
#define N 15
int id[N];
int T,n,m;
int k[N],level[N],a[N][N];
long long c[N][N];
long long p[N];
long long res = 0;
int onenum(int x){
    int res = 0;
    while (x) {
        res ++;
        x &= (x-1);
    }
    return res;
}
void dfs(int x,long long sum,int left){
    res = max(res,sum);
    if(x == 8)
        return ;
    if(x && sum + p[7]-p[x-1] <= res)
        return;
    dfs(x+1,sum,left);
    for(int i = level[id[x]]+1;i<=k[id[x]];i++){
        if(left < c[id[x]][i])
            break;
        dfs(x+1, sum+a[id[x]][i]-a[id[x]][level[id[x]]], left-c[id[x]][i]);
    }
}
int main(){
    scanf("%d",&T);
    for(int z = 1;z<=T;z++){
        res = 0;
        scanf("%d %d",&m,&n);
        for(int i = 0;i<n;i++){
            scanf("%d %d",&k[i],&level[i]);
            for(int j = 1;j<=k[i];j++)
                scanf("%d",&a[i][j]);
            for(int j = 2;j<=k[i];j++)
                scanf("%lld",&c[i][j]);
            for(int j = level[i]+2;j<=k[i];j++)//变成记录从level[i]升级到j级的花费
                c[i][j] += c[i][j-1];
        }
        for(int i = (1<<8)-1;i<(1<<n);i++){//12个选出8个
            if(onenum(i) == 8){
                int tmp = 0;
                long long sum = 0;
                for(int j = 0;j<n;j++)
                    if((1<<j) & i)
                        id[tmp++] = j;
                for(int j = 0;j<8;j++)
                    sum += a[id[j]][level[id[j]]];
                
                p[0] = a[id[0]][k[id[0]]]-a[id[0]][level[id[0]]];
                for(int i = 1;i<8;i++)
                    p[i] = p[i-1] + a[id[i]][k[id[i]]]-a[id[i]][level[id[i]]];       
                dfs(0,sum,m);
            }
        }
        printf("Case #%d: %lld\n",z,res);
    }
    return 0;
}


close all; clc; clear; tic; %% 01 鍙傛暟閰嶇疆 W = 1280; H = 720; save_folder = "data/project"; mkdir(save_folder); save_file_csv = strcat(save_folder, "/","patterns.csv"); % 鐢ㄤ簬鍐欏叆鍒版姇褰变华 n = 4; % 鏍奸浄鐮佷綅鏁� % 鐩哥Щ鍙傛暟 N = 12; % 鐩哥Щ姝ユ暟 A = 130; B = 90; TW = W / (2 ^ n); TH = H / (2 ^ n); %% 02 鐢熸垚鐩哥Щ娉曞浘鍍� [~, patterns_phaseshift_X] = m_make_phase_shift_patterns(A, B, TW, N, W, H); [~, temp_Y] = m_make_phase_shift_patterns(A, B, TH, N, H, W); patterns_phaseshift_Y = zeros(N, H, W); for i = 1: N patterns_phaseshift_Y(i, :, :) = squeeze(temp_Y(i, :, :))'; end %% 03 鐢熸垚鏍奸浄鐮佸浘鍍忥細X鏂瑰悜 patterns_graycode_X = m_make_gray_code_patterns(n, W, H); temp_Y = m_make_gray_code_patterns(n, H, W); [num, H, W] = size(patterns_graycode_X); patterns_graycode_Y = zeros(num, H, W); for i = 1: num patterns_graycode_Y(i, :, :) = squeeze(temp_Y(i, :, :))'; end %% 04 鍐欏叆鍥惧儚 idx = 0; file = fopen(save_file_csv, "w+"); % 鍐欏叆鐩哥Щ鍥炬 X for i = 1: N idx = idx + 1; % 鍐欏叆鍥剧墖 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); disp("鍐欏叆鏂囦欢鍒�:" + save_file_img); img = squeeze(patterns_phaseshift_X(i, :, :)); imwrite(img, save_file_img); % 鍐欏叆csv鏂囦欢 img_row = squeeze(img(1, :)) * 255.; for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 鍐欏叆鏍奸浄鐮佺▼搴� X for i = 1: num idx = idx + 1; % 鍐欏叆鍥惧儚 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); disp("鍐欏叆鏂囦欢鍒�:" + save_file_img); img = squeeze(patterns_graycode_X(i, :, :)); imwrite(img, save_file_img); % 鍐欏叆鍥惧儚 img_row = squeeze(img(1, :)); for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 鍐欏叆鐩哥Щ鍥炬 Y for i = 1: N idx = idx + 1; % 鍐欏叆鍥剧墖 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); disp("鍐欏叆鏂囦欢鍒�:" + save_file_img); img = squeeze(patterns_phaseshift_Y(i, :, :)); imwrite(img, save_file_img); % 鍐欏叆csv鏂囦欢 img_row = squeeze(img(1, :)) * 255.; for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 鍐欏叆鏍奸浄鐮佺▼搴� Y for i = 1: num idx = idx + 1; % 鍐欏叆鍥惧儚 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); disp("鍐欏叆鏂囦欢鍒�:" + save_file_img); img = squeeze(patterns_graycode_Y(i, :, :)); imwrite(img, save_file_img); % 鍐欏叆鍥惧儚 img_row = squeeze(img(1, :)); for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end disp("鍐欏叆瀹屾垚"); fclose(file); toc;close all; clc; clear; tic; %% 01 鍙傛暟閰嶇疆 calib_folder = "data/calib"; N = 12; n = 4; num = n + 2; B_min = 10; % 浣庝簬杩欎釜璋冨埗搴︾殑鎴戜滑灏辫涓哄畠鐨勭浉浣嶄俊鎭笉鍙潬 IT = 0.5; % 鏍奸浄鐮侀槇鍊� win_size = 7; % 涓�兼护娉㈢獥鍙eぇ灏� W = 1280; H = 720; points_per_row = 7; points_per_col = 6; w = 2; load("data/calib/camera_imagePoints.mat"); [~, ~, calib_num] = size(imagePoints); prjPoints = zeros(size(imagePoints)); %% 02 鏍囧畾鎶曞奖浠�佺浉鏈� for calib_idx = 1: calib_num disp(calib_idx); data_folder = calib_folder + "/" + num2str(calib_idx); %% 02 杩戜技鏌ョ湅鍥惧儚鍦嗗績 img = 255 - imread(data_folder + "/18.bmp"); for i = 1: points_per_row * points_per_col xy = imagePoints(i, :, calib_idx); x = round(xy(1)); y = round(xy(2)); img(y, x) = 255; end figure(); mesh(img); %% 03 瑙\Y鐩镐綅 files_phaseShiftX = cell(1, N); idx = 1; for i = 1: N files_phaseShiftX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end files_grayCodeX = cell(1, num); for i = 1: num files_grayCodeX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end files_phaseShiftY = cell(1, N); for i = 1: N files_phaseShiftY{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end files_grayCodeY = cell(1, num); for i = 1: num files_grayCodeY{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end [phaX, difX] = m_calc_absolute_phase(files_phaseShiftX, files_grayCodeX, IT, B_min, win_size); [phaY, difY] = m_calc_absolute_phase(files_phaseShiftY, files_grayCodeY, IT, B_min, win_size); phaX = phaX * W; phaY = phaY * H; for i = 1: points_per_row * points_per_col xy = imagePoints(i, :, calib_idx); x = xy(1); y = xy(2); x_round = round(x); y_round = round(y); % 瀵箈銆亂闄勮繎瀵圭浉浣嶈繘琛屾牱鏉℃洸绾挎彃鍊� xs = zeros(1, 2 * w + 1); ys = zeros(1, 2 * w + 1); phas_x = zeros(1, 2 * w + 1); phas_y = zeros(1, 2 * w + 1); ii = 1; for j = - 1 * w: w xs(1, ii) = x_round + j; ys(1, ii) = y_round + j; phas_x(1, ii) = phaX(y_round, xs(1, ii)); phas_y(1, ii) = phaY(ys(1, ii), x_round); ii = ii + 1; end pha_x = spline(xs, phas_x, x); pha_y = spline(ys, phas_y, y); prjPoints(i, :, calib_idx) = [pha_x, pha_y]; end end save(calib_folder + "\projector_imagePoints.mat", 'prjPoints'); toc;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 3D recosntruction with the calibrated triangular stereo model. % Related Reference: % "Calibration of fringe projection profilometry: A comparative review" % Shijie Feng, Chao Zuo, Liang Zhang, Tianyang Tao, Yan Hu, Wei Yin, Jiaming Qian, and Qian Chen % last modified on 07/27/2020 % by Shijie Feng (Email: shijiefeng@njust.edu.cn) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Clear everything existing. clc; clear; close all; data_folder = "data/model"; N = 12; n = 4; num = n + 2; B_min = 10; % 浣庝簬杩欎釜璋冨埗搴︾殑鎴戜滑灏辫涓哄畠鐨勭浉浣嶄俊鎭笉鍙潬 IT = 0.5; % 鏍奸浄鐮侀槇鍊� win_size = 7; % 涓�兼护娉㈢獥鍙eぇ灏� %% step1: input parameters width = 1280; % camera width height = 1024; % camera height prj_width = 1280; % projector width %camera: Projection matrix Pc load('CamCalibResult.mat'); Kc = KK; % 鐩告満鍐呭弬 Ac = Kc * [Rc_1, Tc_1]; %projector: Projection matrix Pp load('PrjCalibResult.mat'); Kp = KK; % 鎶曞奖浠唴鍙� Ap = Kp * [Rc_1, Tc_1]; %% step2: 璇诲彇娴嬭瘯鍥剧墖骞朵笖璁$畻涓夌淮閲嶅缓 % % 鏉$汗棰戠巼64锛屼篃鏄棿璺濓紙涓�涓懆鏈熺敱64涓儚绱犵粍鎴愶級鐢ㄤ簬璁$畻缁濆鐩镐綅锛岄鐜�1銆�8鐢ㄤ簬鍖呰9鐩镐綅灞曞紑 % f = 64; % 鏉$汗棰戠巼锛堝崟涓懆鏈熸潯绾圭殑鍍忕礌涓暟锛夛紝鍗砅 % load('up_test_obj.mat'); % up_test_obj = up_test_obj / f; % 灏嗙浉浣嶅綊涓�鍖栧埌[0, 2pi]涔嬮棿 % % figure; imshow(up_test_obj / (2 * pi)); colorbar; title("鐩镐綅鍥�, freq=" + num2str(f)); % figure; mesh(up_test_obj); colorbar; title("鐩镐綅鍥�, freq=" + num2str(f)); % % % 璁$畻鎶曞奖浠潗鏍� % x_p = up_test_obj / (2 * pi) * prj_width; idx = 1; files_phaseShiftX = cell(1, N); for i = 1: N files_phaseShiftX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end files_grayCodeX = cell(1, num); for i = 1: num files_grayCodeX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end [phaX, difX] = m_calc_absolute_phase(files_phaseShiftX, files_grayCodeX, IT, B_min, win_size); up_test_obj = phaX * 2 * pi; x_p = phaX * prj_width; % 3D閲嶅缓 Xws = nan(height, width); Yws = nan(height, width); Zws = nan(height, width); for y = 1:height for x = 1:width if ~(up_test_obj(y, x) == 0) uc = x - 1; vc = y - 1; up = (x_p(y, x) - 1); % Eq. (32) in the reference paper. A = [Ac(1,1) - Ac(3,1) * uc, Ac(1,2) - Ac(3,2) * uc, Ac(1,3) - Ac(3,3) * uc; Ac(2,1) - Ac(3,1) * vc, Ac(2,2) - Ac(3,2) * vc, Ac(2,3) - Ac(3,3) * vc; Ap(1,1) - Ap(3,1) * up, Ap(1,2) - Ap(3,2) * up, Ap(1,3) - Ap(3,3) * up]; b = [Ac(3,4) * uc - Ac(1,4); Ac(3,4) * vc - Ac(2,4); Ap(3,4) * up - Ap(1,4)]; XYZ_w = inv(A) * b; Xws(y, x) = XYZ_w(1); Yws(y, x) = XYZ_w(2); Zws(y, x) = XYZ_w(3); end end end % 鐐逛簯鏄剧ず xyzPoints(:, 1) = Xws(:); xyzPoints(:, 2) = Yws(:); xyzPoints(:, 3) = Zws(:); ptCloud = pointCloud(xyzPoints); xlimits = [min(Xws(:)), max(Xws(:))]; ylimits = [min(Yws(:)), max(Yws(:))]; zlimits = ptCloud.ZLimits; player = pcplayer(xlimits, ylimits, zlimits); xlabel(player.Axes,'X (mm)'); ylabel(player.Axes,'Y (mm)'); zlabel(player.Axes,'Z (mm)'); view(player,ptCloud); 这是代码主体部分,接下来给出功能函数function [pha_absolute, dif] = m_calc_absolute_phase(files_phaseShift, files_grayCode, IT, B_min, win_size) [~, N] = size(files_phaseShift); [pha_wrapped, B] = m_calc_warppred_phase(files_phaseShift, N); [~, n] = size(files_grayCode); n = n - 2; % 鎶曞奖浜嗕竴榛戜竴鐧戒袱骞呭浘鐗� Ks = m_calc_gray_code(files_grayCode, IT, n); pha_absolute = pha_wrapped + 2 * pi .* Ks; % 璋冨埗搴︽护娉� B_mask = B > B_min; pha_absolute = pha_absolute .* B_mask; % 杈圭紭璺冲彉璇樊 [pha_absolute, dif] = m_filter2d(pha_absolute, win_size); % 褰掍竴鍖� pha_absolute = pha_absolute / (2 * pi * 2^ n); endfunction [Ks] = m_calc_gray_code(files, IT, n) % 01 璇诲彇姣忎竴寮犲浘鐗囪繘Is [~, num] = size(files); img = imread(files{1}); [h, w] = size(img); Is = zeros(num, h, w); for i = 1: num img = imread(files{i}); Is(i, :, :) = double(img); end % 02 璁$畻Is_Max銆両s_Min锛屽姣忎釜鐐硅繘琛岄槇鍊煎垽鏂� Is_max = max(Is); Is_min = min(Is); Is_std = (Is - Is_min) ./ (Is_max - Is_min); gcs = Is_std > IT; % 03 瀵规瘡涓儚绱犵偣锛岃绠楃紪鐮佸�糣 Vs_row = zeros(1, 2 ^ n, 'uint8'); codes = m_gray_code(n); for i = 1: 2 ^ n code = str2mat(codes(i)); %#ok<DSTRMT> V = 0; for j = 1: n V = V + str2num(code(j)) * 2^ (4 - j); %#ok<ST2NM> end Vs_row(1, i) = V; end % 04 寤虹珛 V - > K 鐨勬槧灏勮〃 V2K = containers.Map(); for K = 1: 2 ^ n V = Vs_row(1, K); V2K(int2str(V)) = K - 1; end Ks = zeros(h, w); for v = 1: h %disp(strcat("绗�", int2str(v), "琛�")); for u = 1: w % 涓嶉渶瑕佹渶鍚庨粦銆佺櫧涓ゅ箙鍥剧墖鐨勭紪鐮� gc = gcs(1: n, v, u); V = 0; for i = 1: n V = V + gc(i) * 2 ^ (4 - i); end % 涓昏鐨勬�ц兘鐡堕 Ks(v, u) = V2K(int2str(V)); end end end function [Ks] = m_calc_gray_code(files, IT, n) % 01 璇诲彇姣忎竴寮犲浘鐗囪繘Is [~, num] = size(files); img = imread(files{1}); [h, w] = size(img); Is = zeros(num, h, w); for i = 1: num img = imread(files{i}); Is(i, :, :) = double(img); end % 02 璁$畻Is_Max銆両s_Min锛屽姣忎釜鐐硅繘琛岄槇鍊煎垽鏂� Is_max = max(Is); Is_min = min(Is); Is_std = (Is - Is_min) ./ (Is_max - Is_min); gcs = Is_std > IT; % 03 瀵规瘡涓儚绱犵偣锛岃绠楃紪鐮佸�糣 Vs_row = zeros(1, 2 ^ n, 'uint8'); codes = m_gray_code(n); for i = 1: 2 ^ n code = str2mat(codes(i)); %#ok<DSTRMT> V = 0; for j = 1: n V = V + str2num(code(j)) * 2^ (4 - j); %#ok<ST2NM> end Vs_row(1, i) = V; end % 04 寤虹珛 V - > K 鐨勬槧灏勮〃 V2K = containers.Map(); for K = 1: 2 ^ n V = Vs_row(1, K); V2K(int2str(V)) = K - 1; end Ks = zeros(h, w); for v = 1: h %disp(strcat("绗�", int2str(v), "琛�")); for u = 1: w % 涓嶉渶瑕佹渶鍚庨粦銆佺櫧涓ゅ箙鍥剧墖鐨勭紪鐮� gc = gcs(1: n, v, u); V = 0; for i = 1: n V = V + gc(i) * 2 ^ (4 - i); end % 涓昏鐨勬�ц兘鐡堕 Ks(v, u) = V2K(int2str(V)); end end end %% 计算包裹相位 function [pha, B] = m_calc_warppred_phase(files, N) sin_sum = 0; cos_sum = 0; for k = 0: N - 1 Ik = m_imread(files{k + 1}); % 读取图片 Ik = m_filter2d(Ik); sin_sum = sin_sum + Ik * sin(2 * k * pi / N); cos_sum = cos_sum + Ik * cos(2 * k * pi / N); end % 根据计算相位、调制度 pha = atan2(sin_sum, cos_sum); B = sqrt(sin_sum .^ 2 + cos_sum .^ 2) * 2 / N; %% 尝试注释掉这段,自己从零实现一遍 % 为了将波折相位转为单个周期内单调递增 pha = - pha; pha_low_mask = pha <= 0; pha = pha + pha_low_mask .* 2. * pi; end %% 读取图片 function [img] = m_imread(file) img = imread(file); img = double(((img(:, :, 1)))); % 转换灰度图 end %% 高斯滤波 function [img] = m_filter2d(img) w = 3.; sigma = 1.; kernel = fspecial("gaussian", [w, w], sigma); img = imfilter(img, kernel, "replicate"); end% 滤波 function [pha_new, dif] = m_filter2d(pha, win_size) % 中值滤波(格雷码边缘处计算出现问题) pha_new = medfilt2(pha, [win_size, win_size]); % (剔除未编码区域) dif = pha - pha_new; endfunction [code] = m_gray_code(n) if (n < 1) disp("鏍奸浄鐮佹暟閲忓繀椤诲ぇ浜�0"); return; elseif (n == 1) % 浜х敓0銆�1 涓や釜鏁板瓧 code = ["0", "1"]; % 杩斿洖code else code_pre = m_gray_code(n - 1); [~, num] = size(code_pre); % 鍒濆鍖栦竴涓暟缁� code = repmat("", 1, num * 2); % step1锛氭瘡涓瓧绗︿覆鍓嶉潰閮�+0 idx = 0; for i = 1: num idx = idx + 1; code(idx) = "0" + code_pre(i); end % step2锛氱炕杞涓厓绱狅紝鍏朵綑鍙栧绉� for i = num: -1: 1 idx = idx + 1; code(idx) = "1" + code_pre(i); end end endfunction [patterns] = m_make_gray_code_patterns(n, W, H) codes = m_gray_code(n); % 灏嗗瓧绗︿覆鏍奸浄鐮佽浆鎹负鐭╅樀鏍煎紡 [~, num] = size(codes); codes_mat = zeros(n, num, 'int8'); for col = 1: num code_col = str2mat(codes(col)); %#ok<DSTRMT> for row = 1: n codes_mat(row, col) = str2num(code_col(row)); %#ok<ST2NM> end end W_per = round(W / num); % 姣忓紶鍥剧墖 patterns = zeros(n + 2, H, W, "uint8"); for idx = 1: n % 涓�琛屽浘鐗� row_one = zeros(1, W, "uint8"); % 姣忎釜鏍煎瓙 for i = 1 : num gray = codes_mat(idx, i); % 鏍煎瓙閲屾瘡涓儚绱� for w = 1: W_per row_one(1, (i - 1) * W_per + w) = gray; end end row_one = row_one * 255; pattern = repmat(row_one, H, 1); patterns(idx, :, :) = pattern; end % 鍏ㄩ粦銆佸叏鐧藉浘鐗囷紝鐢ㄤ簬纭畾姣忎釜鍍忕礌闃堝�� patterns(n + 2, :, :) = ones(H, W, 'uint8') * 255; end % 函数:生成相移条纹 function [Is, Is_img] = m_make_phase_shift_patterns(A, B, T, N, W, H) Is = cell(N, 1); Is_img = zeros(N, H, W); xs = 1: W; f_2pi = 1. / double(T) * 2. * pi; for k = 0: N - 1 Is{k + 1} = A + B * cos(f_2pi * xs + 2 * k / N * pi); Is_img(k + 1, :, :) = repmat(Is{k + 1} / 255., H, 1); end end 请一句一句的解释代码,我是小白
最新发布
09-19
以下是对提供的代码进行逐行解释,该代码主要包含相移条纹生成、格雷码处理、三维重建等功能: ```matlab % 清除所有图形窗口,清空命令窗口,清除工作区变量 close all; clc; clear; % 开始计时 tic; %% 01 参数配置 % 定义图像的宽度 W = 1280; % 定义图像的高度 H = 720; % 定义保存文件的文件夹路径 save_folder = "data/project"; % 创建保存文件的文件夹 mkdir(save_folder); % 定义保存图案信息的 CSV 文件路径 save_file_csv = strcat(save_folder, "/","patterns.csv"); % 定义格雷码的位数 n = 4; % 相移参数 % 定义相移步数 N = 12; % 定义相移条纹的背景亮度 A = 130; % 定义相移条纹的调制幅度 B = 90; % 计算条纹的宽度和高度 TW = W / (2 ^ n); TH = H / (2 ^ n); %% 02 生成相移法图像 % 调用 m_make_phase_shift_patterns 函数生成水平方向的相移条纹图案 [~, patterns_phaseshift_X] = m_make_phase_shift_patterns(A, B, TW, N, W, H); % 调用 m_make_phase_shift_patterns 函数生成垂直方向的相移条纹图案 [~, temp_Y] = m_make_phase_shift_patterns(A, B, TH, N, H, W); % 对垂直方向的相移条纹图案进行转置操作 patterns_phaseshift_Y = zeros(N, H, W); for i = 1: N patterns_phaseshift_Y(i, :, :) = squeeze(temp_Y(i, :, :))'; end %% 03 生成格雷码图像:X 方向 % 调用 m_make_gray_code_patterns 函数生成水平方向的格雷码图案 patterns_graycode_X = m_make_gray_code_patterns(n, W, H); % 调用 m_make_gray_code_patterns 函数生成垂直方向的格雷码图案 temp_Y = m_make_gray_code_patterns(n, H, W); % 获取水平方向格雷码图案的尺寸信息 [num, H, W] = size(patterns_graycode_X); % 对垂直方向的格雷码图案进行转置操作 patterns_graycode_Y = zeros(num, H, W); for i = 1: num patterns_graycode_Y(i, :, :) = squeeze(temp_Y(i, :, :))'; end %% 04 写入图像 % 初始化图像索引 idx = 0; % 打开 CSV 文件以写入数据 file = fopen(save_file_csv, "w+"); % 写入水平方向的相移图案 for i = 1: N idx = idx + 1; % 定义保存相移图案图像的文件路径 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); % 显示正在写入的文件信息 disp("写入文件到:" + save_file_img); % 获取当前相移图案的图像数据 img = squeeze(patterns_phaseshift_X(i, :, :)); % 将相移图案图像保存为 BMP 文件 imwrite(img, save_file_img); % 将相移图案的第一行数据写入 CSV 文件 img_row = squeeze(img(1, :)) * 255.; for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 写入水平方向的格雷码图案 for i = 1: num idx = idx + 1; % 定义保存格雷码图案图像的文件路径 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); % 显示正在写入的文件信息 disp("写入文件到:" + save_file_img); % 获取当前格雷码图案的图像数据 img = squeeze(patterns_graycode_X(i, :, :)); % 将格雷码图案图像保存为 BMP 文件 imwrite(img, save_file_img); % 将格雷码图案的第一行数据写入 CSV 文件 img_row = squeeze(img(1, :)); for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 写入垂直方向的相移图案 for i = 1: N idx = idx + 1; % 定义保存相移图案图像的文件路径 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); % 显示正在写入的文件信息 disp("写入文件到:" + save_file_img); % 获取当前相移图案的图像数据 img = squeeze(patterns_phaseshift_Y(i, :, :)); % 将相移图案图像保存为 BMP 文件 imwrite(img, save_file_img); % 将相移图案的第一行数据写入 CSV 文件 img_row = squeeze(img(1, :)) * 255.; for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 写入垂直方向的格雷码图案 for i = 1: num idx = idx + 1; % 定义保存格雷码图案图像的文件路径 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); % 显示正在写入的文件信息 disp("写入文件到:" + save_file_img); % 获取当前格雷码图案的图像数据 img = squeeze(patterns_graycode_Y(i, :, :)); % 将格雷码图案图像保存为 BMP 文件 imwrite(img, save_file_img); % 将格雷码图案的第一行数据写入 CSV 文件 img_row = squeeze(img(1, :)); for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 显示写入完成信息 disp("写入完成"); % 关闭 CSV 文件 fclose(file); % 停止计时并显示运行时间 toc; % 清除所有图形窗口,清空命令窗口,清除工作区变量 close all; clc; clear; % 开始计时 tic; %% 01 参数配置 % 定义校准数据的文件夹路径 calib_folder = "data/calib"; % 相移步数 N = 12; % 格雷码位数 n = 4; % 格雷码图案的数量 num = n + 2; % 定义最低调制度阈值 B_min = 10; % 定义格雷码的阈值 IT = 0.5; % 定义中值滤波的窗口大小 win_size = 7; % 图像的宽度 W = 1280; % 图像的高度 H = 720; % 每行的校准点数量 points_per_row = 7; % 每列的校准点数量 points_per_col = 6; % 插值窗口的大小 w = 2; % 加载相机图像点数据 load("data/calib/camera_imagePoints.mat"); % 获取图像点数据的尺寸信息 [~, ~, calib_num] = size(imagePoints); % 初始化投影仪图像点数据 prjPoints = zeros(size(imagePoints)); %% 02 校准投影仪、相机 for calib_idx = 1: calib_num % 显示当前校准的索引 disp(calib_idx); % 定义当前校准数据的文件夹路径 data_folder = calib_folder + "/" + num2str(calib_idx); %% 02 近似查看图像圆心 % 读取图像并进行反转操作 img = 255 - imread(data_folder + "/18.bmp"); for i = 1: points_per_row * points_per_col % 获取当前相机图像点的坐标 xy = imagePoints(i, :, calib_idx); % 对坐标进行取整操作 x = round(xy(1)); y = round(xy(2)); % 在图像上标记相机图像点 img(y, x) = 255; end % 显示标记后的图像 figure(); mesh(img); %% 03 解析\Y 绝对相位 % 初始化水平方向相移条纹图像文件路径 files_phaseShiftX = cell(1, N); idx = 1; for i = 1: N files_phaseShiftX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end % 初始化水平方向格雷码图像文件路径 files_grayCodeX = cell(1, num); for i = 1: num files_grayCodeX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end % 初始化垂直方向相移条纹图像文件路径 files_phaseShiftY = cell(1, N); for i = 1: N files_phaseShiftY{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end % 初始化垂直方向格雷码图像文件路径 files_grayCodeY = cell(1, num); for i = 1: num files_grayCodeY{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end % 调用 m_calc_absolute_phase 函数计算水平方向的绝对相位和相位差 [phaX, difX] = m_calc_absolute_phase(files_phaseShiftX, files_grayCodeX, IT, B_min, win_size); % 调用 m_calc_absolute_phase 函数计算垂直方向的绝对相位和相位差 [phaY, difY] = m_calc_absolute_phase(files_phaseShiftY, files_grayCodeY, IT, B_min, win_size); % 将绝对相位转换为像素坐标 phaX = phaX * W; phaY = phaY * H; for i = 1: points_per_row * points_per_col % 获取当前相机图像点的坐标 xy = imagePoints(i, :, calib_idx); x = xy(1); y = xy(2); % 对坐标进行取整操作 x_round = round(x); y_round = round(y); % 初始化插值所需的数据 xs = zeros(1, 2 * w + 1); ys = zeros(1, 2 * w + 1); phas_x = zeros(1, 2 * w + 1); phas_y = zeros(1, 2 * w + 1); ii = 1; for j = - 1 * w: w % 定义插值点的坐标 xs(1, ii) = x_round + j; ys(1, ii) = y_round + j; % 获取插值点的绝对相位 phas_x(1, ii) = phaX(y_round, xs(1, ii)); phas_y(1, ii) = phaY(ys(1, ii), x_round); ii = ii + 1; end % 进行样条插值计算水平方向的绝对相位 pha_x = spline(xs, phas_x, x); % 进行样条插值计算垂直方向的绝对相位 pha_y = spline(ys, phas_y, y); % 将插值后的绝对相位作为投影仪图像点的坐标 prjPoints(i, :, calib_idx) = [pha_x, pha_y]; end end % 保存投影仪图像点数据 save(calib_folder + "\projector_imagePoints.mat", 'prjPoints'); % 停止计时并显示运行时间 toc; %% Clear everything existing. % 清除所有图形窗口,清空命令窗口,清除工作区变量 clc; clear; close all; % 定义测试数据的文件夹路径 data_folder = "data/model"; % 相移步数 N = 12; % 格雷码位数 n = 4; % 格雷码图案的数量 num = n + 2; % 定义最低调制度阈值 B_min = 10; % 定义格雷码的阈值 IT = 0.5; % 定义中值滤波的窗口大小 win_size = 7; % 相机图像的宽度 width = 1280; % 相机图像的高度 height = 1024; % 投影仪图像的宽度 prj_width = 1280; % 加载相机校准结果 load('CamCalibResult.mat'); % 获取相机的内参矩阵 Kc = KK; % 计算相机的投影矩阵 Ac = Kc * [Rc_1, Tc_1]; % 加载投影仪校准结果 load('PrjCalibResult.mat'); % 获取投影仪的内参矩阵 Kp = KK; % 计算投影仪的投影矩阵 Ap = Kp * [Rc_1, Tc_1]; %% step2: 读取测试图像并且计算三维重建 % 初始化水平方向相移条纹图像文件路径 idx = 1; files_phaseShiftX = cell(1, N); for i = 1: N files_phaseShiftX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end % 初始化水平方向格雷码图像文件路径 files_grayCodeX = cell(1, num); for i = 1: num files_grayCodeX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end % 调用 m_calc_absolute_phase 函数计算水平方向的绝对相位和相位差 [phaX, difX] = m_calc_absolute_phase(files_phaseShiftX, files_grayCodeX, IT, B_min, win_size); % 将绝对相位转换为弧度 up_test_obj = phaX * 2 * pi; % 将绝对相位转换为投影仪像素坐标 x_p = phaX * prj_width; % 初始化三维重建的点云数据 Xws = nan(height, width); Yws = nan(height, width); Zws = nan(height, width); for y = 1:height for x = 1:width if ~(up_test_obj(y, x) == 0) % 计算相机图像点的归一化坐标 uc = x - 1; vc = y - 1; % 计算投影仪图像点的归一化坐标 up = (x_p(y, x) - 1); % 构建线性方程组的系数矩阵 A = [Ac(1,1) - Ac(3,1) * uc, Ac(1,2) - Ac(3,2) * uc, Ac(1,3) - Ac(3,3) * uc; Ac(2,1) - Ac(3,1) * vc, Ac(2,2) - Ac(3,2) * vc, Ac(2,3) - Ac(3,3) * vc; Ap(1,1) - Ap(3,1) * up, Ap(1,2) - Ap(3,2) * up, Ap(1,3) - Ap(3,3) * up]; % 构建线性方程组的常数向量 b = [Ac(3,4) * uc - Ac(1,4); Ac(3,4) * vc - Ac(2,4); Ap(3,4) * up - Ap(1,4)]; % 求解线性方程组得到三维点的坐标 XYZ_w = inv(A) * b; % 保存三维点的坐标 Xws(y, x) = XYZ_w(1); Yws(y, x) = XYZ_w(2); Zws(y, x) = XYZ_w(3); end end end % 将三维点的坐标转换为点云对象 xyzPoints(:, 1) = Xws(:); xyzPoints(:, 2) = Yws(:); xyzPoints(:, 3) = Zws(:); ptCloud = pointCloud(xyzPoints); % 获取 X 轴的范围 xlimits = [min(Xws(:)), max(Xws(:))]; % 获取 Y 轴的范围 ylimits = [min(Yws(:)), max(Yws(:))]; % 获取 Z 轴的范围 zlimits = ptCloud.ZLimits; % 创建点云可视化窗口 player = pcplayer(xlimits, ylimits, zlimits); % 设置 X 轴的标签 xlabel(player.Axes
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值