diff --git a/src/PBBiology/include/PBLane.h b/src/PBBiology/include/PBLane.h index e68b448..bd5896a 100644 --- a/src/PBBiology/include/PBLane.h +++ b/src/PBBiology/include/PBLane.h @@ -16,47 +16,53 @@ public: ~PBLane(); private: - //泳道过滤处理函数 - //根据输入所有类似泳道的中心X轴坐标(groupsX),以及泳道的最小最大距离(minDifference/maxDifference),过滤掉不合规的泳道 std::vector processArray(std::vector& groupsX, int minDifference, int maxDifference); - //宽度/*流*/计算函数,用来计算检测泳道宽度流 vector get_bar_num(vector buf); - //泳道检测补全函数 - //根据泳道位置(processX)和泳道间距离(meanW),从图像(src)中检测临近类泳道位置是否符合泳道特性(泳道内两条像素的宽度流应类似且存在条带) std::vector checkArray(std::vector& processX, Mat src, int start_y, int end_y, int meanW); - //条带信息计算函数,输入8bit数组(rbuf)以及过滤范围(range)(此范围内仅保留一个分子) vector> get_top_point(vector rbuf, int range); - //单个泳道中条带信息计算(条带位置等) - BandInfo get_protein_lane_data(Mat src, Rect lane); static bool myCompare(const int& a, const int& b); static bool myCompare2(const std::array& a, const std::array& b); public: - //函数:获得图像中泳道位置 - //src:输入图像,需是8bit单通道图像 - //返回值:泳道矩形位置信息 - std::vector getProteinRect(Mat src); + // std::vector getProteinRect(Mat src); + //鑾峰緱铔嬬櫧娉抽亾浣嶇疆锛宻rc鏄伆搴﹀浘鍍廋V_8UC1锛*ProteinRect_width 鏄泲鐧芥吵閬撳搴︼紙keep_width = 1鏃讹紝杈撳叆鍥哄畾瀹藉害锛沰eep_width = 0鏃,杈撳嚭璁$畻寰楀埌瀹藉害锛夛紝 + //ProteinRect_height_ratio楂樺害姣斾緥锛岄珮搴﹀崰鍥惧儚楂樺害鐧惧垎涔嬪嚑锛屼竴鑸緭鍏90 + //杩斿洖鎵鏈夎泲鐧芥吵閬撶煩褰 + std::vector getProteinRect(Mat src,int* ProteinRect_width,bool keep_width,int ProteinRect_height_ratio); + //娣诲姞娉抽亾锛宲roteinRect鏄綋鍓嶆吵閬撶煩褰紝x鏄柊娣诲姞娉抽亾鐨勪腑蹇儀鍧愭爣锛屼竴鑸氨鏄紶鏍囩偣鍑诲浘褰㈢殑x鍧愭爣, + //src鏄緭鍏ュ浘褰紙CV_16UC1锛,unadjustbands鏄湭瀵归綈鏉″甫淇℃伅锛岄渶瑕佸悓姝ヤ慨鏀 + void addProteinRect(std::vector& proteinRect,int x,Mat src,std::vector& unadjustbands); + //鍒犻櫎娉抽亾锛宲roteinRect鏄綋鍓嶆吵閬撶煩褰紝idx鏄垹闄ゆ吵閬撶殑涓嬫爣搴忓彿,unadjustbands鏄湭瀵归綈鏉″甫淇℃伅锛岄渶瑕佸悓姝ヤ慨鏀 + void deleteProteinRect(std::vector& proteinRect,int idx,std::vector& unadjustbands); + //璁$畻鍗曚釜娉抽亾鏉″甫淇℃伅锛宻rc鏄緭鍏ュ浘褰紙CV_16UC1锛夛紝lane鏄吵閬撳搴旂煩褰紝 + //杩斿洖BandInfo鏉″甫缁撴灉 + BandInfo get_protein_lane_data(Mat src,Rect lane); + //鑾峰緱鎵鏈夋吵閬撴湭瀵归綈鐨勬潯甯︾粨鏋滐紝src鏄緭鍏ュ浘褰紙CV_16UC1锛夛紝lane鏄吵閬撳搴旂煩褰 + //杩斿洖鎵鏈夋吵閬撴湭瀵归綈鐨勬潯甯︾粨鏋 + std::vector getProteinBands(Mat src,std::vector lanes); + //淇敼娉抽亾瀹藉害鍜岄珮搴﹀拰宸茬粡璁$畻鍑虹殑鏈榻愭潯甯︿俊鎭紝src鏄緭鍏ュ浘褰紙CV_16UC1锛夛紝proteinRect鏄綋鍓嶆吵閬撶煩褰紝 + //ProteinRect_width鏄柊鐨勮泲鐧芥吵閬撳搴,ProteinRect_height_ratio鏄柊鐨勯珮搴︽瘮渚嬶紝楂樺害鍗犲浘鍍忛珮搴︾櫨鍒嗕箣鍑狅紝涓鑸緭鍏90 + //unadjustbands鏄湭瀵归綈鐨勬墍鏈夋吵閬撴潯甯︿俊鎭 + //杈撳叆鐨勬潯甯﹀繀椤绘槸鏈榻愮殑锛岃皟鏁村悗鏁版嵁闇瑕侀噸鏂板榻愬拰璁$畻鍒嗗瓙閲忥紙璋冪敤adjustBands鍜宮olecularWeightResult锛 + void modifyProteinRectAndBands(Mat src,std::vector& proteinRect,int ProteinRect_width,int ProteinRect_height_ratio,std::vector& unadjustbands); + //鏍规嵁榧犳爣鐐瑰嚮鍥惧舰鐨勫潗鏍囷紝杈撳嚭褰撳墠浣嶇疆鐨勬吵閬撲笅鏍囧拰鏉″甫涓嬫爣 + //lanes鏄吵閬撲俊鎭紝bands鏄搴旀潯甯︿俊鎭紙涓嶅叧蹇冨榻愭垨鑰呮湭瀵归綈锛夛紝x銆亂鏄潗鏍囷紝lanesIndex鏄紶鍥為紶鏍囩偣鍑讳綅缃殑娉抽亾涓嬫爣锛宐andsIndex鏄紶鏍囩偣鍑讳綅缃殑鏉″甫涓嬫爣 + void getLaneBandsIndex(std::vector lanes,std::vector bands,int x,int y,int* lanesIndex,int* bandsIndex); + //鏍规嵁榧犳爣鐐瑰嚮鍥惧舰鐨勫潗鏍囨坊鍔犳潯甯,lanes鏄吵閬撲俊鎭紝lanesIndex鏄紶鏍囩偣鍑讳綅缃槸绗嚑鏉℃吵閬擄紝unadjustbands鏄湭瀵归綈鐨勬墍鏈夋吵閬撴潯甯︿俊鎭紝鍘熷榧犳爣鐐瑰嚮浣嶇疆鐨剏鍧愭爣 + //杈撳叆鐨勬潯甯﹀繀椤绘槸鏈榻愮殑锛岃皟鏁村悗鏁版嵁闇瑕侀噸鏂板榻愬拰璁$畻鍒嗗瓙閲忥紙璋冪敤adjustBands鍜宮olecularWeightResult锛 + void addProteinBand(std::vector lanes,int lanesIndex,std::vector& unadjustbands,int y); + //鏍规嵁榧犳爣鐐瑰嚮鍥惧舰鐨勫潗鏍囧垹闄ゆ潯甯,lanesIndex鏄紶鏍囩偣鍑讳綅缃槸绗嚑鏉℃吵閬擄紝unadjustbands鏄湭瀵归綈鐨勬墍鏈夋吵閬撴潯甯︿俊鎭紝bandsIndex鏄紶鏍囩偣鍑讳綅缃槸绗嚑涓潯甯 + //杈撳叆鐨勬潯甯﹀繀椤绘槸鏈榻愮殑锛岃皟鏁村悗鏁版嵁闇瑕侀噸鏂板榻愬拰璁$畻鍒嗗瓙閲忥紙璋冪敤adjustBands鍜宮olecularWeightResult锛 + void deleteProteinBand(int lanesIndex,std::vector& unadjustbands,int bandsIndex); + //瀵归綈鎵鏈夋吵閬撶殑鏉″甫缁撴灉锛寀nadjustbands鏄墍鏈夋吵閬撶殑鏉″甫缁撴灉锛宺ange鏄潯甯︿腑蹇冨湪澶氬皯鍍忕礌鑼冨洿鍐呭睘浜庡悓涓绫诲瀷鏉″甫锛屼竴鑸啓10 + //杩斿洖瀵归綈鍚庣殑鎵鏈夋吵閬撶殑鏉″甫缁撴灉锛堟湭璁$畻鍒嗗瓙閲忥級 + std::vector adjustBands(std::vector unadjustbands, int range); + //璁$畻寰楀埌鍒嗗瓙閲忕粨鏋 + void molecularWeightResult(std::vector lanes,std::vector& bands); - ////函数:获得图像中泳道对应的条带信息 - ////src:输入图像,需是16bit单通道图像 - ////lanes:泳道矩形位置信息 - ////返回值:对应条带位置信息 - std::vector getProteinBands(Mat src, std::vector lanes); - - ////函数:条带分子匹配排序函数 - ////bands:所有条带位置信息 - ////range:Y轴差在range范围内的表示和泳道1匹配 - ////返回值:结果修改在bands中 - void adjustBands(std::vector& bands, int range); - - - ////函数:计算所有条带的分子信息 - ////lanes:输入泳道信息 - ////bands:输入条带信息,对应输出的分子信息在这个结构体中 - void molecularWeightResult(std::vector lanes, std::vector& bands); }; \ No newline at end of file diff --git a/src/PBBiology/src/PBLane.cpp b/src/PBBiology/src/PBLane.cpp index 3d2beaf..35d0175 100644 --- a/src/PBBiology/src/PBLane.cpp +++ b/src/PBBiology/src/PBLane.cpp @@ -259,7 +259,7 @@ std::vector PBLane::checkArray(std::vector& processX, Mat src, int sta return result; } -vector> PBLane::get_top_point(vector rbuf, int range) +vector> PBLane::get_top_point(vector rbuf, int range) { vector> point; vector diff(rbuf.size()); @@ -279,7 +279,7 @@ vector> PBLane::get_top_point(vector rbuf, int } for (int i = rbuf.size() - 1; i >= 0; i--) { - if (diff[i] == 0 && i == rbuf.size() - 1) + if (i == rbuf.size() - 1 && diff[i] == 0) { diff[i] = 1; } @@ -437,37 +437,12 @@ vector> PBLane::get_top_point(vector rbuf, int return topPoint; } -BandInfo PBLane::get_protein_lane_data(Mat src, Rect lane) -{ - BandInfo band; - int sum = 0; - vector cdata; - for (int i = lane.y; i < lane.y + lane.height; i++) - { - sum = 0; - for (int j = lane.x; j < lane.x + lane.width; j++) - { - sum += src.at(i, j); - } - sum /= lane.width; - band.land_data.push_back((unsigned short)sum); - band.ydata.push_back((float)((65535 - sum) / 255.0)); - cdata.push_back((unsigned char)((65535 - sum) >> 8)); - } - for (int i = 0; i < lane.height; i++) - { - band.xdata.push_back((float)i / lane.height); - } - band.band_point = get_top_point(cdata, 8); - return band; -} - PBLane::PBLane() {} PBLane::~PBLane() {} -std::vector PBLane::getProteinRect(Mat src) +std::vector PBLane::getProteinRect(Mat src,int* ProteinRect_width,bool keep_width,int ProteinRect_height_ratio) { cv::Mat edges; Canny(src, edges, 50, 150); @@ -478,44 +453,45 @@ std::vector PBLane::getProteinRect(Mat src) std::vector boundingRects; for (const auto& contour : contours) { cv::Rect rect = cv::boundingRect(contour); - double area = rect.area(); + double area = rect.area(); if (area < 20 || area > 700) { - continue; + continue; } double rotia = 0.0; - rotia = (double)rect.width / rect.height; + rotia = (double)rect.width/rect.height; if (rotia >= 7 || rotia <= 2) { - continue; + continue; } boundingRects.push_back(rect); } std::vector allX(boundingRects.size()); - std::vector allY(boundingRects.size()); + std::vector allY(boundingRects.size()); std::vector allW(boundingRects.size()); int up = src.rows; int down = 0; - for (int i = 0; i < boundingRects.size(); i++) + for (int i = 0;i proteinRect1(boundingRects.size()); - return proteinRect1; - } - for (int i = boundingRects.size() / 3; i <= 2 * boundingRects.size() / 3; i++) + for(int i = boundingRects.size()/3;i <= 2*boundingRects.size()/3;i++) { cnt++; meanW += allW[i]; @@ -524,37 +500,99 @@ std::vector PBLane::getProteinRect(Mat src) meanW /= cnt; meanY /= cnt; maxH = max(down - meanY, meanY - up) * 2; - maxH = max(maxH, src.rows / 3); + maxH = max(maxH,src.rows/3); std::vector groupsX; const int n = 3; int sumX = allX[0]; cnt = 1; for (int i = 1; i < boundingRects.size(); i++) { - if (allX[i] - allX[i - 1] > n) + if (allX[i] - allX[i-1] > n) { - groupsX.push_back(sumX / cnt); + groupsX.push_back(sumX/cnt); sumX = 0; cnt = 0; } sumX += allX[i]; cnt++; } - groupsX.push_back(sumX / cnt); + groupsX.push_back(sumX/cnt); - std::vector processX = processArray(groupsX, meanW, meanW * 1.8); - std::vector proteinX = checkArray(processX, src, 15, src.rows - 30, meanW); + std::vector processX = processArray(groupsX,meanW,meanW*1.8); + std::vector proteinX = checkArray(processX, src,15,src.rows - 30,meanW); std::vector proteinRect(proteinX.size()); - for (int i = 0; i < proteinX.size(); i++) + for(int i = 0;i& proteinRect,int x,Mat src,std::vector& unadjustbands) +{ + Rect new_proteinRect; + new_proteinRect.x = x - proteinRect[0].width/2; + new_proteinRect.y = proteinRect[0].y; + new_proteinRect.width = proteinRect[0].width; + new_proteinRect.height = proteinRect[0].height; + BandInfo band = get_protein_lane_data(src,new_proteinRect); + for (auto it = proteinRect.begin(); it != proteinRect.end(); ++it) { + if (it->x > new_proteinRect.x) { + size_t index = std::distance(proteinRect.begin(), it); + proteinRect.insert(it, new_proteinRect); + unadjustbands.insert(unadjustbands.begin() + index, band); + return; + } + } + proteinRect.push_back(new_proteinRect); + unadjustbands.push_back(band); + return; +} + +void PBLane::deleteProteinRect(std::vector& proteinRect,int idx,std::vector& unadjustbands) +{ + if (idx < proteinRect.size()) { + proteinRect.erase(proteinRect.begin() + idx); + unadjustbands.erase(unadjustbands.begin() + idx); + } else { + std::cout << "idx out of range!" << std::endl; + } + return; +} + +BandInfo PBLane::get_protein_lane_data(Mat src, Rect lane) +{ + BandInfo band; + int sum = 0; + vector cdata; + for (int i = lane.y; i < lane.y + lane.height; i++) + { + sum = 0; + for (int j = lane.x; j < lane.x + lane.width; j++) + { + sum += src.at(i, j); + } + sum /= lane.width; + band.land_data.push_back((unsigned short)sum); + band.ydata.push_back((float)((65535 - sum) / 255.0)); + cdata.push_back(65535 - sum); + } + for (int i = 0; i < lane.height; i++) + { + band.xdata.push_back((float)i / lane.height); + } + band.band_point = get_top_point(cdata, 8); + return band; +} std::vector PBLane::getProteinBands(Mat src, std::vector lanes) { @@ -580,11 +618,198 @@ std::vector PBLane::getProteinBands(Mat src, std::vector lan return bands; } +void PBLane::modifyProteinRectAndBands(Mat src,std::vector& proteinRect,int ProteinRect_width,int ProteinRect_height_ratio,std::vector& unadjustbands) +{ + int y_start = src.rows * (100 - ProteinRect_height_ratio) / 200; + int det_y = proteinRect[0].y - y_start; + for(int i = 0;i(i,j); + } + sum/=proteinRect[n].width; + unadjustbands[n].land_data.push_back((unsigned short)sum); + unadjustbands[n].ydata.push_back((float)((65535 - sum)/255.0)); + } + for(int i = 0; i < proteinRect[n].height; i++) + { + unadjustbands[n].xdata.push_back((float)i/proteinRect[n].height); + } -void PBLane::adjustBands(std::vector& bands, int range) + for(int i = 0; i < unadjustbands[n].band_point.size(); i++) + { + //fix left and right + unadjustbands[n].band_point[i][1] += det_y; + unadjustbands[n].band_point[i][2] += det_y; + //fix top + int y1 = unadjustbands[n].band_point[i][1]; + int y2 = unadjustbands[n].band_point[i][2]; + float temp = unadjustbands[n].ydata[y1]; + for(int j = y1 + 1; j < y2; j++) + { + if(unadjustbands[n].ydata[j] > temp){ + temp = unadjustbands[n].ydata[j]; + unadjustbands[n].band_point[i][0] = j; + } + } + } + } +} + +void PBLane::getLaneBandsIndex(std::vector lanes,std::vector bands,int x,int y,int* lanesIndex,int* bandsIndex) { - // 用于存储所有的值及其对应的列索引 - std::map columnMap; + *lanesIndex = -1; + *bandsIndex = -1; + int ystart = lanes[0].y; + int yend = lanes[0].y + lanes[0].height - 1; + if(y > yend || y < ystart) + { + return ; + } + for (int i = 0; i < lanes.size(); i++) { + int xstart = lanes[i].x; + int xend = lanes[i].x + lanes[i].width - 1; + if(x <= xend && x >= xstart){ + *lanesIndex = i; + break; + } + } + for (int j = 0; j < bands[*lanesIndex].band_point.size(); j++) { + int y1 = bands[*lanesIndex].band_point[j][1] + ystart; + int y2 = bands[*lanesIndex].band_point[j][2] + ystart; + if(y <= y2 && y >= y1){ + *bandsIndex = j; + break; + } + } + return; +} + +void PBLane::addProteinBand(std::vector lanes,int lanesIndex,std::vector& unadjustbands,int y) +{ + int ystart = lanes[lanesIndex].y; + int yend = lanes[lanesIndex].y + lanes[lanesIndex].height - 1; + int y1 = 0; + int y2 = lanes[lanesIndex].height; + if(y < ystart || y > yend) + { + return ; + } + int rect_y = y - lanes[lanesIndex].y; + for(int i = 0; i < unadjustbands[lanesIndex].band_point.size(); i++) + { + y2 = unadjustbands[lanesIndex].band_point[i][1]; + if(rect_y >= y1 && rect_y < y2) + { + break; + } + else + { + y1 = unadjustbands[lanesIndex].band_point[i][2]; + } + + } + if(y1 > y2) + { + y2 = lanes[lanesIndex].height; + } + + //fine top + int range = 8; + int top_start = rect_y - range; + int top_end = rect_y + range; + if(top_start < y1){ + top_start = y1; + } + if(top_end > y2){ + top_end = y2; + } + std::array new_band_point; + new_band_point[0] = top_start; + float temp = unadjustbands[lanesIndex].ydata[top_start]; + float mean = unadjustbands[lanesIndex].ydata[top_start]; + for(int i = top_start + 1; i < top_end; i++) + { + mean += unadjustbands[lanesIndex].ydata[i]; + if(unadjustbands[lanesIndex].ydata[i] > temp){ + temp = unadjustbands[lanesIndex].ydata[i]; + new_band_point[0] = i; + } + } + mean /= (top_end - top_start); + + //fine left + temp = unadjustbands[lanesIndex].ydata[new_band_point[0]]; + new_band_point[1] = y1; + for(int i = new_band_point[0] - 1; i > y1; i--) + { + if(unadjustbands[lanesIndex].ydata[i] > temp) + { + if(temp < mean) + { + new_band_point[1] = i+1; + break; + } + } + temp = unadjustbands[lanesIndex].ydata[i]; + } + //fine right + temp = unadjustbands[lanesIndex].ydata[new_band_point[0]]; + new_band_point[2] = y2; + for(int i = new_band_point[0] + 1; i < y2; i++) + { + if(unadjustbands[lanesIndex].ydata[i] > temp) + { + if(temp < mean) + { + new_band_point[2] = i+1; + break; + } + } + temp = unadjustbands[lanesIndex].ydata[i]; + } + + for (auto it = unadjustbands[lanesIndex].band_point.begin(); it != unadjustbands[lanesIndex].band_point.end(); ++it) { + if ((*it)[0] > new_band_point[0]) { + unadjustbands[lanesIndex].band_point.insert(it, new_band_point); + return; + } + } + unadjustbands[lanesIndex].band_point.push_back(new_band_point); + return ; +} + +void PBLane::deleteProteinBand(int lanesIndex,std::vector& unadjustbands,int bandsIndex) +{ + if (bandsIndex < unadjustbands[lanesIndex].band_point.size()) { + unadjustbands[lanesIndex].band_point.erase(unadjustbands[lanesIndex].band_point.begin() + bandsIndex); + } else { + std::cout << "bandsIndex out of range!" << std::endl; + } + return; +} + + +std::vector PBLane::adjustBands(std::vector unadjustbands, int range) +{ + // 鐢ㄤ簬瀛樺偍鎵鏈夌殑鍊煎強鍏跺搴旂殑鍒楃储寮 + std::map columnMap; + std::vector bands = unadjustbands; std::vector> vec; for (int i = 0; i < bands.size(); i++)